mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
Merge branch '1829-self-destruct-timer-introductions' into '804-self-destructing-messages'
Update introduction client to include a self-destruct timer in each message See merge request briar/briar!1300
This commit is contained in:
@@ -64,4 +64,9 @@ public class ValidationUtils {
|
||||
if (dictionary != null && dictionary.size() != size)
|
||||
throw new FormatException();
|
||||
}
|
||||
|
||||
public static void checkRange(@Nullable Long l, long min, long max)
|
||||
throws FormatException {
|
||||
if (l != null && (l < min || l > max)) throw new FormatException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,18 +12,20 @@ public abstract class ConversationMessageHeader {
|
||||
|
||||
private final MessageId id;
|
||||
private final GroupId groupId;
|
||||
private final long timestamp;
|
||||
private final boolean local, sent, seen, read;
|
||||
private final long timestamp, autoDeleteTimer;
|
||||
private final boolean local, read, sent, seen;
|
||||
|
||||
public ConversationMessageHeader(MessageId id, GroupId groupId, long timestamp,
|
||||
boolean local, boolean read, boolean sent, boolean seen) {
|
||||
public ConversationMessageHeader(MessageId id, GroupId groupId,
|
||||
long timestamp, boolean local, boolean read, boolean sent,
|
||||
boolean seen, long autoDeleteTimer) {
|
||||
this.id = id;
|
||||
this.groupId = groupId;
|
||||
this.timestamp = timestamp;
|
||||
this.local = local;
|
||||
this.read = read;
|
||||
this.sent = sent;
|
||||
this.seen = seen;
|
||||
this.read = read;
|
||||
this.autoDeleteTimer = autoDeleteTimer;
|
||||
}
|
||||
|
||||
public MessageId getId() {
|
||||
@@ -55,4 +57,8 @@ public abstract class ConversationMessageHeader {
|
||||
}
|
||||
|
||||
public abstract <T> T accept(ConversationMessageVisitor<T> v);
|
||||
|
||||
public long getAutoDeleteTimer() {
|
||||
return autoDeleteTimer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,12 @@ public abstract class ConversationRequest<N extends Nameable>
|
||||
private final String text;
|
||||
private final boolean answered;
|
||||
|
||||
public ConversationRequest(MessageId messageId, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, N nameable, @Nullable String text,
|
||||
boolean answered) {
|
||||
super(messageId, groupId, time, local, read, sent, seen);
|
||||
public ConversationRequest(MessageId messageId, GroupId groupId,
|
||||
long timestamp, boolean local, boolean read, boolean sent,
|
||||
boolean seen, SessionId sessionId, N nameable,
|
||||
@Nullable String text, boolean answered, long autoDeleteTimer) {
|
||||
super(messageId, groupId, timestamp, local, read, sent, seen,
|
||||
autoDeleteTimer);
|
||||
this.sessionId = sessionId;
|
||||
this.nameable = nameable;
|
||||
this.text = text;
|
||||
|
||||
@@ -16,8 +16,8 @@ public abstract class ConversationResponse extends ConversationMessageHeader {
|
||||
|
||||
public ConversationResponse(MessageId id, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, boolean accepted) {
|
||||
super(id, groupId, time, local, read, sent, seen);
|
||||
SessionId sessionId, boolean accepted, long autoDeleteTimer) {
|
||||
super(id, groupId, time, local, read, sent, seen, autoDeleteTimer);
|
||||
this.sessionId = sessionId;
|
||||
this.accepted = accepted;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public interface IntroductionManager extends ConversationClient {
|
||||
/**
|
||||
* The current minor version of the introduction client.
|
||||
*/
|
||||
int MINOR_VERSION = 0;
|
||||
int MINOR_VERSION = 1;
|
||||
|
||||
/**
|
||||
* Sends two initial introduction messages.
|
||||
|
||||
@@ -18,12 +18,12 @@ public class IntroductionRequest extends ConversationRequest<Author> {
|
||||
|
||||
private final AuthorInfo authorInfo;
|
||||
|
||||
public IntroductionRequest(MessageId messageId, GroupId groupId,
|
||||
long time, boolean local, boolean read, boolean sent, boolean seen,
|
||||
public IntroductionRequest(MessageId messageId, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, Author author, @Nullable String text,
|
||||
boolean answered, AuthorInfo authorInfo) {
|
||||
boolean answered, AuthorInfo authorInfo, long autoDeleteTimer) {
|
||||
super(messageId, groupId, time, local, read, sent, seen, sessionId,
|
||||
author, text, answered);
|
||||
author, text, answered, autoDeleteTimer);
|
||||
this.authorInfo = authorInfo;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,10 @@ public class IntroductionResponse extends ConversationResponse {
|
||||
public IntroductionResponse(MessageId messageId, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, boolean accepted, Author author,
|
||||
AuthorInfo introducedAuthorInfo, Role role, boolean canSucceed) {
|
||||
AuthorInfo introducedAuthorInfo, Role role, boolean canSucceed,
|
||||
long autoDeleteTimer) {
|
||||
super(messageId, groupId, time, local, read, sent, seen, sessionId,
|
||||
accepted);
|
||||
accepted, autoDeleteTimer);
|
||||
this.introducedAuthor = author;
|
||||
this.introducedAuthorInfo = introducedAuthorInfo;
|
||||
this.ourRole = role;
|
||||
|
||||
@@ -16,16 +16,14 @@ public class PrivateMessageHeader extends ConversationMessageHeader {
|
||||
|
||||
private final boolean hasText;
|
||||
private final List<AttachmentHeader> attachmentHeaders;
|
||||
private final long autoDeleteTimer;
|
||||
|
||||
public PrivateMessageHeader(MessageId id, GroupId groupId, long timestamp,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
boolean hasText, List<AttachmentHeader> headers,
|
||||
long autoDeleteTimer) {
|
||||
super(id, groupId, timestamp, local, read, sent, seen);
|
||||
super(id, groupId, timestamp, local, read, sent, seen, autoDeleteTimer);
|
||||
this.hasText = hasText;
|
||||
this.attachmentHeaders = headers;
|
||||
this.autoDeleteTimer = autoDeleteTimer;
|
||||
}
|
||||
|
||||
public boolean hasText() {
|
||||
@@ -36,10 +34,6 @@ public class PrivateMessageHeader extends ConversationMessageHeader {
|
||||
return attachmentHeaders;
|
||||
}
|
||||
|
||||
public long getAutoDeleteTimer() {
|
||||
return autoDeleteTimer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ConversationMessageVisitor<T> v) {
|
||||
return v.visitPrivateMessageHeader(this);
|
||||
|
||||
@@ -7,6 +7,8 @@ import org.briarproject.briar.api.conversation.ConversationRequest;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
|
||||
public abstract class InvitationRequest<S extends Shareable> extends
|
||||
ConversationRequest<S> {
|
||||
|
||||
@@ -17,7 +19,7 @@ public abstract class InvitationRequest<S extends Shareable> extends
|
||||
SessionId sessionId, S object, @Nullable String text,
|
||||
boolean available, boolean canBeOpened) {
|
||||
super(messageId, groupId, time, local, read, sent, seen, sessionId,
|
||||
object, text, !available);
|
||||
object, text, !available, NO_AUTO_DELETE_TIMER);
|
||||
this.canBeOpened = canBeOpened;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
import org.briarproject.briar.api.conversation.ConversationResponse;
|
||||
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
|
||||
public abstract class InvitationResponse extends ConversationResponse {
|
||||
|
||||
private final GroupId shareableId;
|
||||
@@ -12,7 +14,8 @@ public abstract class InvitationResponse extends ConversationResponse {
|
||||
public InvitationResponse(MessageId id, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, boolean accepted, GroupId shareableId) {
|
||||
super(id, groupId, time, local, read, sent, seen, sessionId, accepted);
|
||||
super(id, groupId, time, local, read, sent, seen, sessionId, accepted,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
this.shareableId = shareableId;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ import org.briarproject.briar.api.client.SessionId;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
class AbortMessage extends AbstractIntroductionMessage {
|
||||
@@ -16,7 +18,8 @@ class AbortMessage extends AbstractIntroductionMessage {
|
||||
|
||||
protected AbortMessage(MessageId messageId, GroupId groupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, SessionId sessionId) {
|
||||
super(messageId, groupId, timestamp, previousMessageId);
|
||||
super(messageId, groupId, timestamp, previousMessageId,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
this.sessionId = sessionId;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,13 +16,16 @@ abstract class AbstractIntroductionMessage {
|
||||
private final long timestamp;
|
||||
@Nullable
|
||||
private final MessageId previousMessageId;
|
||||
private final long autoDeleteTimer;
|
||||
|
||||
AbstractIntroductionMessage(MessageId messageId, GroupId groupId,
|
||||
long timestamp, @Nullable MessageId previousMessageId) {
|
||||
long timestamp, @Nullable MessageId previousMessageId,
|
||||
long autoDeleteTimer) {
|
||||
this.messageId = messageId;
|
||||
this.groupId = groupId;
|
||||
this.timestamp = timestamp;
|
||||
this.previousMessageId = previousMessageId;
|
||||
this.autoDeleteTimer = autoDeleteTimer;
|
||||
}
|
||||
|
||||
MessageId getMessageId() {
|
||||
@@ -42,4 +45,7 @@ abstract class AbstractIntroductionMessage {
|
||||
return previousMessageId;
|
||||
}
|
||||
|
||||
public long getAutoDeleteTimer() {
|
||||
return autoDeleteTimer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ 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.ContactId;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||
@@ -17,9 +18,11 @@ 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.GroupId;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
import org.briarproject.briar.api.introduction.IntroductionResponse;
|
||||
@@ -30,6 +33,10 @@ import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.briar.api.introduction.IntroductionManager.CLIENT_ID;
|
||||
import static org.briarproject.briar.api.introduction.IntroductionManager.MAJOR_VERSION;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.GROUP_KEY_CONTACT_ID;
|
||||
import static org.briarproject.briar.introduction.MessageType.ABORT;
|
||||
import static org.briarproject.briar.introduction.MessageType.ACCEPT;
|
||||
import static org.briarproject.briar.introduction.MessageType.ACTIVATE;
|
||||
@@ -39,7 +46,7 @@ import static org.briarproject.briar.introduction.MessageType.REQUEST;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
abstract class AbstractProtocolEngine<S extends Session>
|
||||
abstract class AbstractProtocolEngine<S extends Session<?>>
|
||||
implements ProtocolEngine<S> {
|
||||
|
||||
protected final DatabaseComponent db;
|
||||
@@ -50,6 +57,7 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
protected final IdentityManager identityManager;
|
||||
protected final MessageParser messageParser;
|
||||
protected final MessageEncoder messageEncoder;
|
||||
protected final ClientVersioningManager clientVersioningManager;
|
||||
protected final Clock clock;
|
||||
|
||||
AbstractProtocolEngine(
|
||||
@@ -61,6 +69,7 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
IdentityManager identityManager,
|
||||
MessageParser messageParser,
|
||||
MessageEncoder messageEncoder,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
Clock clock) {
|
||||
this.db = db;
|
||||
this.clientHelper = clientHelper;
|
||||
@@ -70,16 +79,26 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
this.identityManager = identityManager;
|
||||
this.messageParser = messageParser;
|
||||
this.messageEncoder = messageEncoder;
|
||||
this.clientVersioningManager = clientVersioningManager;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
Message sendRequestMessage(Transaction txn, PeerSession s,
|
||||
long timestamp, Author author, @Nullable String text)
|
||||
throws DbException {
|
||||
Message m = messageEncoder
|
||||
.encodeRequestMessage(s.getContactGroupId(), timestamp,
|
||||
s.getLastLocalMessageId(), author, text);
|
||||
sendMessage(txn, REQUEST, s.getSessionId(), m, true);
|
||||
Message m;
|
||||
if (contactSupportsAutoDeletion(txn, s.getContactGroupId())) {
|
||||
// TODO: Look up the current auto-delete timer
|
||||
long timer = NO_AUTO_DELETE_TIMER;
|
||||
m = messageEncoder.encodeRequestMessage(s.getContactGroupId(),
|
||||
timestamp, s.getLastLocalMessageId(), author, text, timer);
|
||||
sendMessage(txn, REQUEST, s.getSessionId(), m, true, timer);
|
||||
} else {
|
||||
m = messageEncoder.encodeRequestMessage(s.getContactGroupId(),
|
||||
timestamp, s.getLastLocalMessageId(), author, text);
|
||||
sendMessage(txn, REQUEST, s.getSessionId(), m, true,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -87,21 +106,41 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
PublicKey ephemeralPublicKey, long acceptTimestamp,
|
||||
Map<TransportId, TransportProperties> transportProperties,
|
||||
boolean visible) throws DbException {
|
||||
Message m = messageEncoder
|
||||
.encodeAcceptMessage(s.getContactGroupId(), timestamp,
|
||||
s.getLastLocalMessageId(), s.getSessionId(),
|
||||
ephemeralPublicKey, acceptTimestamp,
|
||||
transportProperties);
|
||||
sendMessage(txn, ACCEPT, s.getSessionId(), m, visible);
|
||||
Message m;
|
||||
if (contactSupportsAutoDeletion(txn, s.getContactGroupId())) {
|
||||
// TODO: Look up the current auto-delete timer
|
||||
long timer = NO_AUTO_DELETE_TIMER;
|
||||
m = messageEncoder.encodeAcceptMessage(s.getContactGroupId(),
|
||||
timestamp, s.getLastLocalMessageId(), s.getSessionId(),
|
||||
ephemeralPublicKey, acceptTimestamp, transportProperties,
|
||||
timer);
|
||||
sendMessage(txn, ACCEPT, s.getSessionId(), m, visible, timer);
|
||||
} else {
|
||||
m = messageEncoder.encodeAcceptMessage(s.getContactGroupId(),
|
||||
timestamp, s.getLastLocalMessageId(), s.getSessionId(),
|
||||
ephemeralPublicKey, acceptTimestamp, transportProperties);
|
||||
sendMessage(txn, ACCEPT, s.getSessionId(), m, visible,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
Message sendDeclineMessage(Transaction txn, PeerSession s, long timestamp,
|
||||
boolean visible) throws DbException {
|
||||
Message m = messageEncoder
|
||||
.encodeDeclineMessage(s.getContactGroupId(), timestamp,
|
||||
s.getLastLocalMessageId(), s.getSessionId());
|
||||
sendMessage(txn, DECLINE, s.getSessionId(), m, visible);
|
||||
Message m;
|
||||
if (contactSupportsAutoDeletion(txn, s.getContactGroupId())) {
|
||||
// TODO: Look up the current auto-delete timer
|
||||
long timer = NO_AUTO_DELETE_TIMER;
|
||||
m = messageEncoder.encodeDeclineMessage(s.getContactGroupId(),
|
||||
timestamp, s.getLastLocalMessageId(), s.getSessionId(),
|
||||
timer);
|
||||
sendMessage(txn, DECLINE, s.getSessionId(), m, visible, timer);
|
||||
} else {
|
||||
m = messageEncoder.encodeDeclineMessage(s.getContactGroupId(),
|
||||
timestamp, s.getLastLocalMessageId(), s.getSessionId());
|
||||
sendMessage(txn, DECLINE, s.getSessionId(), m, visible,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -111,7 +150,8 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
.encodeAuthMessage(s.getContactGroupId(), timestamp,
|
||||
s.getLastLocalMessageId(), s.getSessionId(), mac,
|
||||
signature);
|
||||
sendMessage(txn, AUTH, s.getSessionId(), m, false);
|
||||
sendMessage(txn, AUTH, s.getSessionId(), m, false,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -120,7 +160,8 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
Message m = messageEncoder
|
||||
.encodeActivateMessage(s.getContactGroupId(), timestamp,
|
||||
s.getLastLocalMessageId(), s.getSessionId(), mac);
|
||||
sendMessage(txn, ACTIVATE, s.getSessionId(), m, false);
|
||||
sendMessage(txn, ACTIVATE, s.getSessionId(), m, false,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -129,16 +170,17 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
Message m = messageEncoder
|
||||
.encodeAbortMessage(s.getContactGroupId(), timestamp,
|
||||
s.getLastLocalMessageId(), s.getSessionId());
|
||||
sendMessage(txn, ABORT, s.getSessionId(), m, false);
|
||||
sendMessage(txn, ABORT, s.getSessionId(), m, false,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
return m;
|
||||
}
|
||||
|
||||
private void sendMessage(Transaction txn, MessageType type,
|
||||
SessionId sessionId, Message m, boolean visibleInConversation)
|
||||
throws DbException {
|
||||
BdfDictionary meta = messageEncoder
|
||||
.encodeMetadata(type, sessionId, m.getTimestamp(), true, true,
|
||||
visibleInConversation);
|
||||
SessionId sessionId, Message m, boolean visibleInConversation,
|
||||
long autoDeleteTimer) throws DbException {
|
||||
BdfDictionary meta = messageEncoder.encodeMetadata(type, sessionId,
|
||||
m.getTimestamp(), true, true, visibleInConversation,
|
||||
autoDeleteTimer);
|
||||
try {
|
||||
clientHelper.addLocalMessage(txn, m, meta, true, false);
|
||||
} catch (FormatException e) {
|
||||
@@ -146,9 +188,10 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
}
|
||||
}
|
||||
|
||||
void broadcastIntroductionResponseReceivedEvent(Transaction txn, Session s,
|
||||
AuthorId sender, Author otherAuthor, AbstractIntroductionMessage m,
|
||||
boolean canSucceed) throws DbException {
|
||||
void broadcastIntroductionResponseReceivedEvent(Transaction txn,
|
||||
Session<?> s, AuthorId sender, Author otherAuthor,
|
||||
AbstractIntroductionMessage m, boolean canSucceed)
|
||||
throws DbException {
|
||||
AuthorId localAuthorId = identityManager.getLocalAuthor(txn).getId();
|
||||
Contact c = contactManager.getContact(txn, sender, localAuthorId);
|
||||
AuthorInfo otherAuthorInfo =
|
||||
@@ -157,7 +200,8 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
new IntroductionResponse(m.getMessageId(), m.getGroupId(),
|
||||
m.getTimestamp(), false, false, false, false,
|
||||
s.getSessionId(), m instanceof AcceptMessage,
|
||||
otherAuthor, otherAuthorInfo, s.getRole(), canSucceed);
|
||||
otherAuthor, otherAuthorInfo, s.getRole(), canSucceed,
|
||||
m.getAutoDeleteTimer());
|
||||
IntroductionResponseReceivedEvent e =
|
||||
new IntroductionResponseReceivedEvent(response, c.getId());
|
||||
txn.attach(e);
|
||||
@@ -190,4 +234,19 @@ abstract class AbstractProtocolEngine<S extends Session>
|
||||
);
|
||||
}
|
||||
|
||||
boolean contactSupportsAutoDeletion(Transaction txn, GroupId contactGroupId)
|
||||
throws DbException {
|
||||
try {
|
||||
BdfDictionary meta = clientHelper
|
||||
.getGroupMetadataAsDictionary(txn, contactGroupId);
|
||||
int contactId = meta.getLong(GROUP_KEY_CONTACT_ID).intValue();
|
||||
ContactId c = new ContactId(contactId);
|
||||
int minorVersion = clientVersioningManager
|
||||
.getClientMinorVersion(txn, c, CLIENT_ID, MAJOR_VERSION);
|
||||
// Auto-delete was added in client version 0.1
|
||||
return minorVersion >= 1;
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,10 @@ class AcceptMessage extends AbstractIntroductionMessage {
|
||||
long timestamp, @Nullable MessageId previousMessageId,
|
||||
SessionId sessionId, PublicKey ephemeralPublicKey,
|
||||
long acceptTimestamp,
|
||||
Map<TransportId, TransportProperties> transportProperties) {
|
||||
super(messageId, groupId, timestamp, previousMessageId);
|
||||
Map<TransportId, TransportProperties> transportProperties,
|
||||
long autoDeleteTimer) {
|
||||
super(messageId, groupId, timestamp, previousMessageId,
|
||||
autoDeleteTimer);
|
||||
this.sessionId = sessionId;
|
||||
this.ephemeralPublicKey = ephemeralPublicKey;
|
||||
this.acceptTimestamp = acceptTimestamp;
|
||||
|
||||
@@ -7,6 +7,8 @@ import org.briarproject.briar.api.client.SessionId;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
class ActivateMessage extends AbstractIntroductionMessage {
|
||||
@@ -17,7 +19,8 @@ class ActivateMessage extends AbstractIntroductionMessage {
|
||||
protected ActivateMessage(MessageId messageId, GroupId groupId,
|
||||
long timestamp, MessageId previousMessageId, SessionId sessionId,
|
||||
byte[] mac) {
|
||||
super(messageId, groupId, timestamp, previousMessageId);
|
||||
super(messageId, groupId, timestamp, previousMessageId,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
this.sessionId = sessionId;
|
||||
this.mac = mac;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import org.briarproject.briar.api.client.SessionId;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
class AuthMessage extends AbstractIntroductionMessage {
|
||||
@@ -17,7 +19,8 @@ class AuthMessage extends AbstractIntroductionMessage {
|
||||
protected AuthMessage(MessageId messageId, GroupId groupId,
|
||||
long timestamp, MessageId previousMessageId, SessionId sessionId,
|
||||
byte[] mac, byte[] signature) {
|
||||
super(messageId, groupId, timestamp, previousMessageId);
|
||||
super(messageId, groupId, timestamp, previousMessageId,
|
||||
NO_AUTO_DELETE_TIMER);
|
||||
this.sessionId = sessionId;
|
||||
this.mac = mac;
|
||||
this.signature = signature;
|
||||
|
||||
@@ -16,8 +16,9 @@ class DeclineMessage extends AbstractIntroductionMessage {
|
||||
|
||||
protected DeclineMessage(MessageId messageId, GroupId groupId,
|
||||
long timestamp, @Nullable MessageId previousMessageId,
|
||||
SessionId sessionId) {
|
||||
super(messageId, groupId, timestamp, previousMessageId);
|
||||
SessionId sessionId, long autoDeleteTimer) {
|
||||
super(messageId, groupId, timestamp, previousMessageId,
|
||||
autoDeleteTimer);
|
||||
this.sessionId = sessionId;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.transport.KeyManager;
|
||||
import org.briarproject.bramble.api.transport.KeySetId;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.client.ProtocolStateException;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
@@ -76,10 +77,11 @@ class IntroduceeProtocolEngine
|
||||
Clock clock,
|
||||
IntroductionCrypto crypto,
|
||||
KeyManager keyManager,
|
||||
TransportPropertyManager transportPropertyManager) {
|
||||
TransportPropertyManager transportPropertyManager,
|
||||
ClientVersioningManager clientVersioningManager) {
|
||||
super(db, clientHelper, contactManager, contactGroupFactory,
|
||||
messageTracker, identityManager, messageParser, messageEncoder,
|
||||
clock);
|
||||
clientVersioningManager, clock);
|
||||
this.crypto = crypto;
|
||||
this.keyManager = keyManager;
|
||||
this.transportPropertyManager = transportPropertyManager;
|
||||
@@ -258,7 +260,7 @@ class IntroduceeProtocolEngine
|
||||
IntroductionRequest request = new IntroductionRequest(m.getMessageId(),
|
||||
m.getGroupId(), m.getTimestamp(), false, false, false, false,
|
||||
s.getSessionId(), m.getAuthor(), m.getText(), false,
|
||||
authorInfo);
|
||||
authorInfo, m.getAutoDeleteTimer());
|
||||
IntroductionRequestReceivedEvent e =
|
||||
new IntroductionRequestReceivedEvent(request, c.getId());
|
||||
txn.attach(e);
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker;
|
||||
import org.briarproject.briar.api.client.ProtocolStateException;
|
||||
import org.briarproject.briar.api.introduction.event.IntroductionAbortedEvent;
|
||||
@@ -50,10 +51,11 @@ class IntroducerProtocolEngine
|
||||
IdentityManager identityManager,
|
||||
MessageParser messageParser,
|
||||
MessageEncoder messageEncoder,
|
||||
ClientVersioningManager clientVersioningManager,
|
||||
Clock clock) {
|
||||
super(db, clientHelper, contactManager, contactGroupFactory,
|
||||
messageTracker, identityManager, messageParser, messageEncoder,
|
||||
clock);
|
||||
clientVersioningManager, clock);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -12,6 +12,7 @@ interface IntroductionConstants {
|
||||
String MSG_KEY_LOCAL = "local";
|
||||
String MSG_KEY_VISIBLE_IN_UI = "visibleInUi";
|
||||
String MSG_KEY_AVAILABLE_TO_ANSWER = "availableToAnswer";
|
||||
String MSG_KEY_AUTO_DELETE_TIMER = "autoDeleteTimer";
|
||||
|
||||
// Session Keys
|
||||
String SESSION_KEY_SESSION_ID = "sessionId";
|
||||
|
||||
@@ -461,7 +461,7 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
return new IntroductionRequest(m, contactGroupId, meta.getTimestamp(),
|
||||
meta.isLocal(), meta.isRead(), status.isSent(), status.isSeen(),
|
||||
sessionId, author, text, !meta.isAvailableToAnswer(),
|
||||
authorInfo);
|
||||
authorInfo, rm.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
private IntroductionResponse parseInvitationResponse(Transaction txn,
|
||||
@@ -499,7 +499,8 @@ class IntroductionManagerImpl extends ConversationClientImpl
|
||||
}
|
||||
return new IntroductionResponse(m, contactGroupId, meta.getTimestamp(),
|
||||
meta.isLocal(), meta.isRead(), status.isSent(), status.isSeen(),
|
||||
sessionId, accept, author, authorInfo, role, canSucceed);
|
||||
sessionId, accept, author, authorInfo, role, canSucceed,
|
||||
meta.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
private void removeSessionWithIntroducer(Transaction txn,
|
||||
|
||||
@@ -15,13 +15,18 @@ import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.MAX_AUTO_DELETE_TIMER_MS;
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS;
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
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.util.ValidationUtils.checkLength;
|
||||
import static org.briarproject.bramble.util.ValidationUtils.checkRange;
|
||||
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
|
||||
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_INTRODUCTION_TEXT_LENGTH;
|
||||
import static org.briarproject.briar.introduction.MessageType.ACCEPT;
|
||||
@@ -52,13 +57,14 @@ class IntroductionValidator extends BdfMessageValidator {
|
||||
return validateRequestMessage(m, body);
|
||||
case ACCEPT:
|
||||
return validateAcceptMessage(m, body);
|
||||
case DECLINE:
|
||||
return validateDeclineMessage(type, m, body);
|
||||
case AUTH:
|
||||
return validateAuthMessage(m, body);
|
||||
case ACTIVATE:
|
||||
return validateActivateMessage(m, body);
|
||||
case DECLINE:
|
||||
case ABORT:
|
||||
return validateOtherMessage(type, m, body);
|
||||
return validateAbortMessage(type, m, body);
|
||||
default:
|
||||
throw new FormatException();
|
||||
}
|
||||
@@ -66,7 +72,11 @@ class IntroductionValidator extends BdfMessageValidator {
|
||||
|
||||
private BdfMessageContext validateRequestMessage(Message m, BdfList body)
|
||||
throws FormatException {
|
||||
checkSize(body, 4);
|
||||
// Client version 0.0: Message type, optional previous message ID,
|
||||
// author, optional text.
|
||||
// Client version 0.1: Message type, optional previous message ID,
|
||||
// author, optional text, optional auto-delete timer.
|
||||
checkSize(body, 4, 5);
|
||||
|
||||
byte[] previousMessageId = body.getOptionalRaw(1);
|
||||
checkLength(previousMessageId, UniqueId.LENGTH);
|
||||
@@ -77,8 +87,11 @@ class IntroductionValidator extends BdfMessageValidator {
|
||||
String text = body.getOptionalString(3);
|
||||
checkLength(text, 1, MAX_INTRODUCTION_TEXT_LENGTH);
|
||||
|
||||
long timer = NO_AUTO_DELETE_TIMER;
|
||||
if (body.size() == 5) timer = validateTimer(body.getOptionalLong(4));
|
||||
|
||||
BdfDictionary meta =
|
||||
messageEncoder.encodeRequestMetadata(m.getTimestamp());
|
||||
messageEncoder.encodeRequestMetadata(m.getTimestamp(), timer);
|
||||
if (previousMessageId == null) {
|
||||
return new BdfMessageContext(meta);
|
||||
} else {
|
||||
@@ -89,7 +102,12 @@ class IntroductionValidator extends BdfMessageValidator {
|
||||
|
||||
private BdfMessageContext validateAcceptMessage(Message m, BdfList body)
|
||||
throws FormatException {
|
||||
checkSize(body, 6);
|
||||
// Client version 0.0: Message type, session ID, optional previous
|
||||
// message ID, ephemeral public key, timestamp, transport properties.
|
||||
// Client version 0.1: Message type, session ID, optional previous
|
||||
// message ID, ephemeral public key, timestamp, transport properties,
|
||||
// optional auto-delete timer.
|
||||
checkSize(body, 6, 7);
|
||||
|
||||
byte[] sessionIdBytes = body.getRaw(1);
|
||||
checkLength(sessionIdBytes, UniqueId.LENGTH);
|
||||
@@ -109,9 +127,40 @@ class IntroductionValidator extends BdfMessageValidator {
|
||||
clientHelper
|
||||
.parseAndValidateTransportPropertiesMap(transportProperties);
|
||||
|
||||
long timer = NO_AUTO_DELETE_TIMER;
|
||||
if (body.size() == 7) timer = validateTimer(body.getOptionalLong(6));
|
||||
|
||||
SessionId sessionId = new SessionId(sessionIdBytes);
|
||||
BdfDictionary meta = messageEncoder.encodeMetadata(ACCEPT, sessionId,
|
||||
m.getTimestamp(), false, false, false);
|
||||
m.getTimestamp(), false, false, false, timer);
|
||||
if (previousMessageId == null) {
|
||||
return new BdfMessageContext(meta);
|
||||
} else {
|
||||
MessageId dependency = new MessageId(previousMessageId);
|
||||
return new BdfMessageContext(meta, singletonList(dependency));
|
||||
}
|
||||
}
|
||||
|
||||
private BdfMessageContext validateDeclineMessage(MessageType type,
|
||||
Message m, BdfList body) throws FormatException {
|
||||
// Client version 0.0: Message type, session ID, optional previous
|
||||
// message ID.
|
||||
// Client version 0.1: Message type, session ID, optional previous
|
||||
// message ID, optional auto-delete timer.
|
||||
checkSize(body, 3, 4);
|
||||
|
||||
byte[] sessionIdBytes = body.getRaw(1);
|
||||
checkLength(sessionIdBytes, UniqueId.LENGTH);
|
||||
|
||||
byte[] previousMessageId = body.getOptionalRaw(2);
|
||||
checkLength(previousMessageId, UniqueId.LENGTH);
|
||||
|
||||
long timer = NO_AUTO_DELETE_TIMER;
|
||||
if (body.size() == 4) timer = validateTimer(body.getOptionalLong(3));
|
||||
|
||||
SessionId sessionId = new SessionId(sessionIdBytes);
|
||||
BdfDictionary meta = messageEncoder.encodeMetadata(type, sessionId,
|
||||
m.getTimestamp(), false, false, false, timer);
|
||||
if (previousMessageId == null) {
|
||||
return new BdfMessageContext(meta);
|
||||
} else {
|
||||
@@ -138,7 +187,7 @@ class IntroductionValidator extends BdfMessageValidator {
|
||||
|
||||
SessionId sessionId = new SessionId(sessionIdBytes);
|
||||
BdfDictionary meta = messageEncoder.encodeMetadata(AUTH, sessionId,
|
||||
m.getTimestamp(), false, false, false);
|
||||
m.getTimestamp(), false, false, false, NO_AUTO_DELETE_TIMER);
|
||||
MessageId dependency = new MessageId(previousMessageId);
|
||||
return new BdfMessageContext(meta, singletonList(dependency));
|
||||
}
|
||||
@@ -158,7 +207,7 @@ class IntroductionValidator extends BdfMessageValidator {
|
||||
|
||||
SessionId sessionId = new SessionId(sessionIdBytes);
|
||||
BdfDictionary meta = messageEncoder.encodeMetadata(ACTIVATE, sessionId,
|
||||
m.getTimestamp(), false, false, false);
|
||||
m.getTimestamp(), false, false, false, NO_AUTO_DELETE_TIMER);
|
||||
if (previousMessageId == null) {
|
||||
return new BdfMessageContext(meta);
|
||||
} else {
|
||||
@@ -167,7 +216,7 @@ class IntroductionValidator extends BdfMessageValidator {
|
||||
}
|
||||
}
|
||||
|
||||
private BdfMessageContext validateOtherMessage(MessageType type,
|
||||
private BdfMessageContext validateAbortMessage(MessageType type,
|
||||
Message m, BdfList body) throws FormatException {
|
||||
checkSize(body, 3);
|
||||
|
||||
@@ -179,7 +228,7 @@ class IntroductionValidator extends BdfMessageValidator {
|
||||
|
||||
SessionId sessionId = new SessionId(sessionIdBytes);
|
||||
BdfDictionary meta = messageEncoder.encodeMetadata(type, sessionId,
|
||||
m.getTimestamp(), false, false, false);
|
||||
m.getTimestamp(), false, false, false, NO_AUTO_DELETE_TIMER);
|
||||
if (previousMessageId == null) {
|
||||
return new BdfMessageContext(meta);
|
||||
} else {
|
||||
@@ -188,4 +237,9 @@ class IntroductionValidator extends BdfMessageValidator {
|
||||
}
|
||||
}
|
||||
|
||||
private long validateTimer(@Nullable Long timer) throws FormatException {
|
||||
if (timer == null) return NO_AUTO_DELETE_TIMER;
|
||||
checkRange(timer, MIN_AUTO_DELETE_TIMER_MS, MAX_AUTO_DELETE_TIMER_MS);
|
||||
return timer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,12 @@ import javax.annotation.Nullable;
|
||||
@NotNullByDefault
|
||||
interface MessageEncoder {
|
||||
|
||||
BdfDictionary encodeRequestMetadata(long timestamp);
|
||||
BdfDictionary encodeRequestMetadata(long timestamp,
|
||||
long autoDeleteTimer);
|
||||
|
||||
BdfDictionary encodeMetadata(MessageType type,
|
||||
@Nullable SessionId sessionId, long timestamp, boolean local,
|
||||
boolean read, boolean visible);
|
||||
boolean read, boolean visible, long autoDeleteTimer);
|
||||
|
||||
void addSessionId(BdfDictionary meta, SessionId sessionId);
|
||||
|
||||
@@ -30,18 +31,53 @@ interface MessageEncoder {
|
||||
|
||||
void setAvailableToAnswer(BdfDictionary meta, boolean available);
|
||||
|
||||
/**
|
||||
* Encodes a request message without an auto-delete timer.
|
||||
*/
|
||||
Message encodeRequestMessage(GroupId contactGroupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, Author author,
|
||||
@Nullable String text);
|
||||
|
||||
/**
|
||||
* Encodes a request message with an optional auto-delete timer. This
|
||||
* requires the contact to support client version 0.1 or higher.
|
||||
*/
|
||||
Message encodeRequestMessage(GroupId contactGroupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, Author author,
|
||||
@Nullable String text, long autoDeleteTimer);
|
||||
|
||||
/**
|
||||
* Encodes an accept message without an auto-delete timer.
|
||||
*/
|
||||
Message encodeAcceptMessage(GroupId contactGroupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, SessionId sessionId,
|
||||
PublicKey ephemeralPublicKey, long acceptTimestamp,
|
||||
Map<TransportId, TransportProperties> transportProperties);
|
||||
|
||||
/**
|
||||
* Encodes an accept message with an optional auto-delete timer. This
|
||||
* requires the contact to support client version 0.1 or higher.
|
||||
*/
|
||||
Message encodeAcceptMessage(GroupId contactGroupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, SessionId sessionId,
|
||||
PublicKey ephemeralPublicKey, long acceptTimestamp,
|
||||
Map<TransportId, TransportProperties> transportProperties,
|
||||
long autoDeleteTimer);
|
||||
|
||||
/**
|
||||
* Encodes a decline message without an auto-delete timer.
|
||||
*/
|
||||
Message encodeDeclineMessage(GroupId contactGroupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, SessionId sessionId);
|
||||
|
||||
/**
|
||||
* Encodes a decline message with an optional auto-delete timer. This
|
||||
* requires the contact to support client version 0.1 or higher.
|
||||
*/
|
||||
Message encodeDeclineMessage(GroupId contactGroupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, SessionId sessionId,
|
||||
long autoDeleteTimer);
|
||||
|
||||
Message encodeAuthMessage(GroupId contactGroupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, SessionId sessionId,
|
||||
byte[] mac, byte[] signature);
|
||||
|
||||
@@ -20,7 +20,9 @@ import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_AVAILABLE_TO_ANSWER;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_LOCAL;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_MESSAGE_TYPE;
|
||||
@@ -48,9 +50,10 @@ class MessageEncoderImpl implements MessageEncoder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdfDictionary encodeRequestMetadata(long timestamp) {
|
||||
BdfDictionary meta =
|
||||
encodeMetadata(REQUEST, null, timestamp, false, false, false);
|
||||
public BdfDictionary encodeRequestMetadata(long timestamp,
|
||||
long autoDeleteTimer) {
|
||||
BdfDictionary meta = encodeMetadata(REQUEST, null, timestamp,
|
||||
false, false, false, autoDeleteTimer);
|
||||
meta.put(MSG_KEY_AVAILABLE_TO_ANSWER, false);
|
||||
return meta;
|
||||
}
|
||||
@@ -58,7 +61,7 @@ class MessageEncoderImpl implements MessageEncoder {
|
||||
@Override
|
||||
public BdfDictionary encodeMetadata(MessageType type,
|
||||
@Nullable SessionId sessionId, long timestamp, boolean local,
|
||||
boolean read, boolean visible) {
|
||||
boolean read, boolean visible, long autoDeleteTimer) {
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
meta.put(MSG_KEY_MESSAGE_TYPE, type.getValue());
|
||||
if (sessionId != null)
|
||||
@@ -69,6 +72,9 @@ class MessageEncoderImpl implements MessageEncoder {
|
||||
meta.put(MSG_KEY_LOCAL, local);
|
||||
meta.put(MSG_KEY_READ, read);
|
||||
meta.put(MSG_KEY_VISIBLE_IN_UI, visible);
|
||||
if (autoDeleteTimer != NO_AUTO_DELETE_TIMER) {
|
||||
meta.put(MSG_KEY_AUTO_DELETE_TIMER, autoDeleteTimer);
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
|
||||
@@ -103,6 +109,23 @@ class MessageEncoderImpl implements MessageEncoder {
|
||||
return createMessage(contactGroupId, timestamp, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message encodeRequestMessage(GroupId contactGroupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, Author author,
|
||||
@Nullable String text, long autoDeleteTimer) {
|
||||
if (text != null && text.isEmpty()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
BdfList body = BdfList.of(
|
||||
REQUEST.getValue(),
|
||||
previousMessageId,
|
||||
clientHelper.toList(author),
|
||||
text,
|
||||
encodeTimer(autoDeleteTimer)
|
||||
);
|
||||
return createMessage(contactGroupId, timestamp, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message encodeAcceptMessage(GroupId contactGroupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, SessionId sessionId,
|
||||
@@ -119,11 +142,46 @@ class MessageEncoderImpl implements MessageEncoder {
|
||||
return createMessage(contactGroupId, timestamp, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message encodeAcceptMessage(GroupId contactGroupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, SessionId sessionId,
|
||||
PublicKey ephemeralPublicKey, long acceptTimestamp,
|
||||
Map<TransportId, TransportProperties> transportProperties,
|
||||
long autoDeleteTimer) {
|
||||
BdfList body = BdfList.of(
|
||||
ACCEPT.getValue(),
|
||||
sessionId,
|
||||
previousMessageId,
|
||||
ephemeralPublicKey.getEncoded(),
|
||||
acceptTimestamp,
|
||||
clientHelper.toDictionary(transportProperties),
|
||||
encodeTimer(autoDeleteTimer)
|
||||
);
|
||||
return createMessage(contactGroupId, timestamp, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message encodeDeclineMessage(GroupId contactGroupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, SessionId sessionId) {
|
||||
return encodeMessage(DECLINE, contactGroupId, sessionId, timestamp,
|
||||
previousMessageId);
|
||||
BdfList body = BdfList.of(
|
||||
DECLINE.getValue(),
|
||||
sessionId,
|
||||
previousMessageId
|
||||
);
|
||||
return createMessage(contactGroupId, timestamp, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message encodeDeclineMessage(GroupId contactGroupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, SessionId sessionId,
|
||||
long autoDeleteTimer) {
|
||||
BdfList body = BdfList.of(
|
||||
DECLINE.getValue(),
|
||||
sessionId,
|
||||
previousMessageId,
|
||||
encodeTimer(autoDeleteTimer)
|
||||
);
|
||||
return createMessage(contactGroupId, timestamp, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -156,15 +214,8 @@ class MessageEncoderImpl implements MessageEncoder {
|
||||
@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(),
|
||||
ABORT.getValue(),
|
||||
sessionId,
|
||||
previousMessageId
|
||||
);
|
||||
@@ -181,4 +232,8 @@ class MessageEncoderImpl implements MessageEncoder {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Long encodeTimer(long autoDeleteTimer) {
|
||||
return autoDeleteTimer == NO_AUTO_DELETE_TIMER ? null : autoDeleteTimer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,12 @@ class MessageMetadata {
|
||||
private final MessageType type;
|
||||
@Nullable
|
||||
private final SessionId sessionId;
|
||||
private final long timestamp;
|
||||
private final long timestamp, autoDeleteTimer;
|
||||
private final boolean local, read, visible, available;
|
||||
|
||||
MessageMetadata(MessageType type, @Nullable SessionId sessionId,
|
||||
long timestamp, boolean local, boolean read, boolean visible,
|
||||
boolean available) {
|
||||
boolean available, long autoDeleteTimer) {
|
||||
this.type = type;
|
||||
this.sessionId = sessionId;
|
||||
this.timestamp = timestamp;
|
||||
@@ -26,6 +26,7 @@ class MessageMetadata {
|
||||
this.read = read;
|
||||
this.visible = visible;
|
||||
this.available = available;
|
||||
this.autoDeleteTimer = autoDeleteTimer;
|
||||
}
|
||||
|
||||
MessageType getMessageType() {
|
||||
@@ -57,4 +58,7 @@ class MessageMetadata {
|
||||
return available;
|
||||
}
|
||||
|
||||
public long getAutoDeleteTimer() {
|
||||
return autoDeleteTimer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,9 @@ import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.briar.client.MessageTrackerConstants.MSG_KEY_READ;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_AVAILABLE_TO_ANSWER;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_LOCAL;
|
||||
import static org.briarproject.briar.introduction.IntroductionConstants.MSG_KEY_MESSAGE_TYPE;
|
||||
@@ -65,8 +67,9 @@ 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);
|
||||
long timer = d.getLong(MSG_KEY_AUTO_DELETE_TIMER, NO_AUTO_DELETE_TIMER);
|
||||
return new MessageMetadata(type, sessionId, timestamp, local, read,
|
||||
visible, available);
|
||||
visible, available, timer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,8 +80,10 @@ class MessageParserImpl implements MessageParser {
|
||||
new MessageId(previousMsgBytes));
|
||||
Author author = clientHelper.parseAndValidateAuthor(body.getList(2));
|
||||
String text = body.getOptionalString(3);
|
||||
long timer = NO_AUTO_DELETE_TIMER;
|
||||
if (body.size() == 5) timer = body.getLong(4, NO_AUTO_DELETE_TIMER);
|
||||
return new RequestMessage(m.getId(), m.getGroupId(),
|
||||
m.getTimestamp(), previousMessageId, author, text);
|
||||
m.getTimestamp(), previousMessageId, author, text, timer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,9 +97,11 @@ class MessageParserImpl implements MessageParser {
|
||||
long acceptTimestamp = body.getLong(4);
|
||||
Map<TransportId, TransportProperties> transportProperties = clientHelper
|
||||
.parseAndValidateTransportPropertiesMap(body.getDictionary(5));
|
||||
long timer = NO_AUTO_DELETE_TIMER;
|
||||
if (body.size() == 7) timer = body.getLong(6, NO_AUTO_DELETE_TIMER);
|
||||
return new AcceptMessage(m.getId(), m.getGroupId(), m.getTimestamp(),
|
||||
previousMessageId, sessionId, ephemeralPublicKey,
|
||||
acceptTimestamp, transportProperties);
|
||||
acceptTimestamp, transportProperties, timer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -104,8 +111,10 @@ class MessageParserImpl implements MessageParser {
|
||||
byte[] previousMsgBytes = body.getOptionalRaw(2);
|
||||
MessageId previousMessageId = (previousMsgBytes == null ? null :
|
||||
new MessageId(previousMsgBytes));
|
||||
long timer = NO_AUTO_DELETE_TIMER;
|
||||
if (body.size() == 4) timer = body.getLong(3, NO_AUTO_DELETE_TIMER);
|
||||
return new DeclineMessage(m.getId(), m.getGroupId(), m.getTimestamp(),
|
||||
previousMessageId, sessionId);
|
||||
previousMessageId, sessionId, timer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,8 +18,9 @@ class RequestMessage extends AbstractIntroductionMessage {
|
||||
|
||||
RequestMessage(MessageId messageId, GroupId groupId, long timestamp,
|
||||
@Nullable MessageId previousMessageId, Author author,
|
||||
@Nullable String text) {
|
||||
super(messageId, groupId, timestamp, previousMessageId);
|
||||
@Nullable String text, long autoDeleteTimer) {
|
||||
super(messageId, groupId, timestamp, previousMessageId,
|
||||
autoDeleteTimer);
|
||||
this.author = author;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.MIN_AU
|
||||
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
|
||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
||||
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
|
||||
import static org.briarproject.bramble.util.ValidationUtils.checkRange;
|
||||
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
|
||||
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_ATTACHMENTS_PER_MESSAGE;
|
||||
import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_CONTENT_TYPE_BYTES;
|
||||
@@ -136,10 +137,10 @@ class PrivateMessageValidator implements MessageValidator {
|
||||
checkLength(contentType, 1, MAX_CONTENT_TYPE_BYTES);
|
||||
}
|
||||
Long timer = null;
|
||||
if (body.size() == 4) timer = body.getOptionalLong(3);
|
||||
if (timer != null && (timer < MIN_AUTO_DELETE_TIMER_MS ||
|
||||
timer > MAX_AUTO_DELETE_TIMER_MS)) {
|
||||
throw new FormatException();
|
||||
if (body.size() == 4) {
|
||||
timer = body.getOptionalLong(3);
|
||||
checkRange(timer, MIN_AUTO_DELETE_TIMER_MS,
|
||||
MAX_AUTO_DELETE_TIMER_MS);
|
||||
}
|
||||
// Return the metadata
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
|
||||
@@ -45,6 +45,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.bramble.test.TestPluginConfigModule.SIMPLEX_TRANSPORT_ID;
|
||||
import static org.briarproject.bramble.test.TestUtils.getAgreementPublicKey;
|
||||
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||
@@ -1114,7 +1115,7 @@ public class IntroductionIntegrationTest
|
||||
m.getTimestamp(), m.getPreviousMessageId(),
|
||||
m.getSessionId(), m.getEphemeralPublicKey(),
|
||||
m.getAcceptTimestamp(),
|
||||
getTransportPropertiesMap(2))
|
||||
getTransportPropertiesMap(2), NO_AUTO_DELETE_TIMER)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1125,7 +1126,7 @@ public class IntroductionIntegrationTest
|
||||
m.getTimestamp(), m.getPreviousMessageId(),
|
||||
m.getSessionId(), m.getEphemeralPublicKey(),
|
||||
clock.currentTimeMillis(),
|
||||
m.getTransportProperties())
|
||||
m.getTransportProperties(), NO_AUTO_DELETE_TIMER)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1135,7 +1136,8 @@ public class IntroductionIntegrationTest
|
||||
m -> new AcceptMessage(m.getMessageId(), m.getGroupId(),
|
||||
m.getTimestamp(), m.getPreviousMessageId(),
|
||||
m.getSessionId(), getAgreementPublicKey(),
|
||||
m.getAcceptTimestamp(), m.getTransportProperties())
|
||||
m.getAcceptTimestamp(), m.getTransportProperties(),
|
||||
NO_AUTO_DELETE_TIMER)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1155,10 +1157,12 @@ public class IntroductionIntegrationTest
|
||||
|
||||
// introducer can not yet remove messages
|
||||
assertFalse(deleteAllMessages1From0().allDeleted());
|
||||
assertTrue(deleteAllMessages1From0().hasIntroductionSessionInProgress());
|
||||
assertTrue(
|
||||
deleteAllMessages1From0().hasIntroductionSessionInProgress());
|
||||
// introducee1 can not yet remove messages
|
||||
assertFalse(deleteAllMessages0From1().allDeleted());
|
||||
assertTrue(deleteAllMessages0From1().hasIntroductionSessionInProgress());
|
||||
assertTrue(
|
||||
deleteAllMessages0From1().hasIntroductionSessionInProgress());
|
||||
|
||||
// sync second REQUEST message
|
||||
sync0To2(1, true);
|
||||
@@ -1166,10 +1170,12 @@ public class IntroductionIntegrationTest
|
||||
|
||||
// introducer can not yet remove messages
|
||||
assertFalse(deleteAllMessages2From0().allDeleted());
|
||||
assertTrue(deleteAllMessages2From0().hasIntroductionSessionInProgress());
|
||||
assertTrue(
|
||||
deleteAllMessages2From0().hasIntroductionSessionInProgress());
|
||||
// introducee2 can not yet remove messages
|
||||
assertFalse(deleteAllMessages0From2().allDeleted());
|
||||
assertTrue(deleteAllMessages0From2().hasIntroductionSessionInProgress());
|
||||
assertTrue(
|
||||
deleteAllMessages0From2().hasIntroductionSessionInProgress());
|
||||
|
||||
// sync first ACCEPT message
|
||||
sync1To0(1, true);
|
||||
@@ -1177,7 +1183,8 @@ public class IntroductionIntegrationTest
|
||||
|
||||
// introducer can not yet remove messages
|
||||
assertFalse(deleteAllMessages1From0().allDeleted());
|
||||
assertTrue(deleteAllMessages1From0().hasIntroductionSessionInProgress());
|
||||
assertTrue(
|
||||
deleteAllMessages1From0().hasIntroductionSessionInProgress());
|
||||
|
||||
// sync second ACCEPT message
|
||||
sync2To0(1, true);
|
||||
@@ -1185,7 +1192,8 @@ public class IntroductionIntegrationTest
|
||||
|
||||
// introducer can not yet remove messages
|
||||
assertFalse(deleteAllMessages2From0().allDeleted());
|
||||
assertTrue(deleteAllMessages2From0().hasIntroductionSessionInProgress());
|
||||
assertTrue(
|
||||
deleteAllMessages2From0().hasIntroductionSessionInProgress());
|
||||
|
||||
// sync forwarded ACCEPT messages to introducees
|
||||
sync0To1(1, true);
|
||||
@@ -1193,10 +1201,12 @@ public class IntroductionIntegrationTest
|
||||
|
||||
// introducee1 can not yet remove messages
|
||||
assertFalse(deleteAllMessages0From1().allDeleted());
|
||||
assertTrue(deleteAllMessages0From1().hasIntroductionSessionInProgress());
|
||||
assertTrue(
|
||||
deleteAllMessages0From1().hasIntroductionSessionInProgress());
|
||||
// introducee2 can not yet remove messages
|
||||
assertFalse(deleteAllMessages0From2().allDeleted());
|
||||
assertTrue(deleteAllMessages0From2().hasIntroductionSessionInProgress());
|
||||
assertTrue(
|
||||
deleteAllMessages0From2().hasIntroductionSessionInProgress());
|
||||
|
||||
// sync first AUTH and its forward
|
||||
sync1To0(1, true);
|
||||
@@ -1204,12 +1214,15 @@ public class IntroductionIntegrationTest
|
||||
|
||||
// introducer can not yet remove messages
|
||||
assertFalse(deleteAllMessages1From0().allDeleted());
|
||||
assertTrue(deleteAllMessages1From0().hasIntroductionSessionInProgress());
|
||||
assertTrue(
|
||||
deleteAllMessages1From0().hasIntroductionSessionInProgress());
|
||||
assertFalse(deleteAllMessages2From0().allDeleted());
|
||||
assertTrue(deleteAllMessages2From0().hasIntroductionSessionInProgress());
|
||||
assertTrue(
|
||||
deleteAllMessages2From0().hasIntroductionSessionInProgress());
|
||||
// introducee2 can not yet remove messages
|
||||
assertFalse(deleteAllMessages0From2().allDeleted());
|
||||
assertTrue(deleteAllMessages0From2().hasIntroductionSessionInProgress());
|
||||
assertTrue(
|
||||
deleteAllMessages0From2().hasIntroductionSessionInProgress());
|
||||
|
||||
// sync second AUTH and its forward as well as the following ACTIVATE
|
||||
sync2To0(2, true);
|
||||
@@ -1217,12 +1230,15 @@ public class IntroductionIntegrationTest
|
||||
|
||||
// introducer can not yet remove messages
|
||||
assertFalse(deleteAllMessages1From0().allDeleted());
|
||||
assertTrue(deleteAllMessages1From0().hasIntroductionSessionInProgress());
|
||||
assertTrue(
|
||||
deleteAllMessages1From0().hasIntroductionSessionInProgress());
|
||||
assertFalse(deleteAllMessages2From0().allDeleted());
|
||||
assertTrue(deleteAllMessages2From0().hasIntroductionSessionInProgress());
|
||||
assertTrue(
|
||||
deleteAllMessages2From0().hasIntroductionSessionInProgress());
|
||||
// introducee1 can not yet remove messages
|
||||
assertFalse(deleteAllMessages0From1().allDeleted());
|
||||
assertTrue(deleteAllMessages0From1().hasIntroductionSessionInProgress());
|
||||
assertTrue(
|
||||
deleteAllMessages0From1().hasIntroductionSessionInProgress());
|
||||
|
||||
// sync second ACTIVATE and its forward
|
||||
sync1To0(1, true);
|
||||
@@ -1458,14 +1474,16 @@ public class IntroductionIntegrationTest
|
||||
sendAcks(c1, c0, contactId0From1, 1);
|
||||
assertTrue(deleteAllMessages1From0().allDeleted());
|
||||
assertEquals(0, getMessages1From0().size());
|
||||
assertTrue(deleteAllMessages1From0().allDeleted()); // a second time nothing happens
|
||||
assertTrue(deleteAllMessages1From0()
|
||||
.allDeleted()); // a second time nothing happens
|
||||
|
||||
// introducer can remove messages after getting ACK from introducee2
|
||||
// if this succeeds, we still had the session object after delete above
|
||||
sendAcks(c2, c0, contactId0From2, 1);
|
||||
assertTrue(deleteAllMessages2From0().allDeleted());
|
||||
assertEquals(0, getMessages2From0().size());
|
||||
assertTrue(deleteAllMessages2From0().allDeleted()); // a second time nothing happens
|
||||
assertTrue(deleteAllMessages2From0()
|
||||
.allDeleted()); // a second time nothing happens
|
||||
|
||||
// no one should have aborted
|
||||
assertFalse(listener0.aborted);
|
||||
@@ -1489,7 +1507,8 @@ public class IntroductionIntegrationTest
|
||||
Set<MessageId> toDelete1 = new HashSet<>();
|
||||
toDelete1.add(messageId1);
|
||||
assertFalse(deleteMessages1From0(toDelete1).allDeleted());
|
||||
assertTrue(deleteMessages1From0(toDelete1).hasIntroductionSessionInProgress());
|
||||
assertTrue(deleteMessages1From0(toDelete1)
|
||||
.hasIntroductionSessionInProgress());
|
||||
|
||||
// deleting the introduction for introducee2 will fail as well
|
||||
Collection<ConversationMessageHeader> m2From0 = getMessages2From0();
|
||||
@@ -1498,7 +1517,8 @@ public class IntroductionIntegrationTest
|
||||
Set<MessageId> toDelete2 = new HashSet<>();
|
||||
toDelete2.add(messageId2);
|
||||
assertFalse(deleteMessages2From0(toDelete2).allDeleted());
|
||||
assertTrue(deleteMessages2From0(toDelete2).hasIntroductionSessionInProgress());
|
||||
assertTrue(deleteMessages2From0(toDelete2)
|
||||
.hasIntroductionSessionInProgress());
|
||||
|
||||
// sync REQUEST messages
|
||||
sync0To1(1, true);
|
||||
@@ -1508,9 +1528,11 @@ public class IntroductionIntegrationTest
|
||||
|
||||
// deleting introduction fails, because responses did not arrive
|
||||
assertFalse(deleteMessages0From1(toDelete1).allDeleted());
|
||||
assertTrue(deleteMessages0From1(toDelete1).hasIntroductionSessionInProgress());
|
||||
assertTrue(deleteMessages0From1(toDelete1)
|
||||
.hasIntroductionSessionInProgress());
|
||||
assertFalse(deleteMessages0From2(toDelete2).allDeleted());
|
||||
assertTrue(deleteMessages0From2(toDelete2).hasIntroductionSessionInProgress());
|
||||
assertTrue(deleteMessages0From2(toDelete2)
|
||||
.hasIntroductionSessionInProgress());
|
||||
|
||||
// remember response of introducee1 for future deletion
|
||||
Collection<ConversationMessageHeader> m0From1 = getMessages0From1();
|
||||
@@ -1570,7 +1592,8 @@ public class IntroductionIntegrationTest
|
||||
// deleting introduction fails for introducee 2,
|
||||
// because response is not yet selected for deletion
|
||||
assertFalse(deleteMessages0From2(toDelete2).allDeleted());
|
||||
assertTrue(deleteMessages0From2(toDelete2).hasNotAllIntroductionSelected());
|
||||
assertTrue(deleteMessages0From2(toDelete2)
|
||||
.hasNotAllIntroductionSelected());
|
||||
|
||||
// add response to be deleted as well
|
||||
toDelete2.add(response2);
|
||||
@@ -1588,7 +1611,8 @@ public class IntroductionIntegrationTest
|
||||
// deleting introduction fails for introducee 1,
|
||||
// because response is not yet selected for deletion
|
||||
assertFalse(deleteMessages0From1(toDelete1).allDeleted());
|
||||
assertTrue(deleteMessages0From1(toDelete1).hasNotAllIntroductionSelected());
|
||||
assertTrue(deleteMessages0From1(toDelete1)
|
||||
.hasNotAllIntroductionSelected());
|
||||
|
||||
// add response to be deleted as well
|
||||
toDelete1.add(response1);
|
||||
@@ -1730,7 +1754,8 @@ public class IntroductionIntegrationTest
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
private abstract class IntroductionListener implements EventListener {
|
||||
private abstract static class IntroductionListener
|
||||
implements EventListener {
|
||||
|
||||
volatile boolean aborted = false;
|
||||
volatile Event latestEvent;
|
||||
|
||||
@@ -6,20 +6,29 @@ import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
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.plugin.TransportId;
|
||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.test.ValidatorTestCase;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
import org.jmock.Expectations;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.MAX_AUTO_DELETE_TIMER_MS;
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS;
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAC_BYTES;
|
||||
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES;
|
||||
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_SIGNATURE_BYTES;
|
||||
import static org.briarproject.bramble.test.TestUtils.getAgreementPublicKey;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||
import static org.briarproject.bramble.test.TestUtils.getTransportId;
|
||||
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||
import static org.briarproject.briar.api.introduction.IntroductionConstants.MAX_INTRODUCTION_TEXT_LENGTH;
|
||||
import static org.briarproject.briar.introduction.MessageType.ABORT;
|
||||
@@ -44,9 +53,12 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
private final BdfDictionary meta = new BdfDictionary();
|
||||
private final PublicKey ephemeralPublicKey = getAgreementPublicKey();
|
||||
private final long acceptTimestamp = 42;
|
||||
private final TransportId transportId = getTransportId();
|
||||
private final BdfDictionary transportProperties = BdfDictionary.of(
|
||||
new BdfEntry("transportId", new BdfDictionary())
|
||||
new BdfEntry(transportId.getString(), new BdfDictionary())
|
||||
);
|
||||
private final Map<TransportId, TransportProperties> transportPropertiesMap =
|
||||
singletonMap(transportId, new TransportProperties());
|
||||
private final byte[] mac = getRandomBytes(MAC_BYTES);
|
||||
private final byte[] signature = getRandomBytes(MAX_SIGNATURE_BYTES);
|
||||
|
||||
@@ -60,7 +72,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
authorList, text);
|
||||
|
||||
expectParseAuthor(authorList, author);
|
||||
expectEncodeRequestMetadata();
|
||||
expectEncodeRequestMetadata(NO_AUTO_DELETE_TIMER);
|
||||
BdfMessageContext messageContext =
|
||||
validator.validateMessage(message, group, body);
|
||||
|
||||
@@ -72,7 +84,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
BdfList body = BdfList.of(REQUEST.getValue(), null, authorList, text);
|
||||
|
||||
expectParseAuthor(authorList, author);
|
||||
expectEncodeRequestMetadata();
|
||||
expectEncodeRequestMetadata(NO_AUTO_DELETE_TIMER);
|
||||
BdfMessageContext messageContext =
|
||||
validator.validateMessage(message, group, body);
|
||||
|
||||
@@ -84,13 +96,42 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
BdfList body = BdfList.of(REQUEST.getValue(), null, authorList, null);
|
||||
|
||||
expectParseAuthor(authorList, author);
|
||||
expectEncodeRequestMetadata();
|
||||
expectEncodeRequestMetadata(NO_AUTO_DELETE_TIMER);
|
||||
BdfMessageContext messageContext =
|
||||
validator.validateMessage(message, group, body);
|
||||
|
||||
assertExpectedContext(messageContext, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptsRequestWithNullAutoDeleteTimer() throws Exception {
|
||||
testAcceptsRequestWithAutoDeleteTimer(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptsRequestWithMinAutoDeleteTimer() throws Exception {
|
||||
testAcceptsRequestWithAutoDeleteTimer(MIN_AUTO_DELETE_TIMER_MS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptsRequestWithMaxAutoDeleteTimer() throws Exception {
|
||||
testAcceptsRequestWithAutoDeleteTimer(MAX_AUTO_DELETE_TIMER_MS);
|
||||
}
|
||||
|
||||
private void testAcceptsRequestWithAutoDeleteTimer(@Nullable Long timer)
|
||||
throws Exception {
|
||||
BdfList body = BdfList.of(REQUEST.getValue(), previousMsgId.getBytes(),
|
||||
authorList, text, timer);
|
||||
|
||||
expectParseAuthor(authorList, author);
|
||||
long autoDeleteTimer = timer == null ? NO_AUTO_DELETE_TIMER : timer;
|
||||
expectEncodeRequestMetadata(autoDeleteTimer);
|
||||
BdfMessageContext messageContext =
|
||||
validator.validateMessage(message, group, body);
|
||||
|
||||
assertExpectedContext(messageContext, previousMsgId);
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testRejectsTooShortBodyForRequest() throws Exception {
|
||||
BdfList body = BdfList.of(REQUEST.getValue(), null, authorList);
|
||||
@@ -99,8 +140,8 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testRejectsTooLongBodyForRequest() throws Exception {
|
||||
BdfList body =
|
||||
BdfList.of(REQUEST.getValue(), null, authorList, text, null);
|
||||
BdfList body = BdfList.of(REQUEST.getValue(), null, authorList, text,
|
||||
null, null);
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
@@ -119,6 +160,32 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testRejectsRequestWithNonLongAutoDeleteTimer()
|
||||
throws Exception {
|
||||
BdfList body = BdfList.of(REQUEST.getValue(), previousMsgId.getBytes(),
|
||||
authorList, text, "foo");
|
||||
expectParseAuthor(authorList, author);
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testRejectsRequestWithTooSmallAutoDeleteTimer()
|
||||
throws Exception {
|
||||
BdfList body = BdfList.of(REQUEST.getValue(), previousMsgId.getBytes(),
|
||||
authorList, text, MIN_AUTO_DELETE_TIMER_MS - 1);
|
||||
expectParseAuthor(authorList, author);
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testRejectsRequestWithTooBigAutoDeleteTimer() throws Exception {
|
||||
BdfList body = BdfList.of(REQUEST.getValue(), previousMsgId.getBytes(),
|
||||
authorList, text, MAX_AUTO_DELETE_TIMER_MS + 1);
|
||||
expectParseAuthor(authorList, author);
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
//
|
||||
// Introduction ACCEPT
|
||||
//
|
||||
@@ -129,11 +196,38 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
previousMsgId.getBytes(), ephemeralPublicKey.getEncoded(),
|
||||
acceptTimestamp, transportProperties);
|
||||
expectParsePublicKey();
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).parseAndValidateTransportPropertiesMap(
|
||||
transportProperties);
|
||||
}});
|
||||
expectEncodeMetadata(ACCEPT);
|
||||
expectParseTransportProperties();
|
||||
expectEncodeMetadata(ACCEPT, NO_AUTO_DELETE_TIMER);
|
||||
BdfMessageContext messageContext =
|
||||
validator.validateMessage(message, group, body);
|
||||
|
||||
assertExpectedContext(messageContext, previousMsgId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptsAcceptWithNullAutoDeleteTimer() throws Exception {
|
||||
testAcceptsAcceptWithAutoDeleteTimer(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptsAcceptWithMinAutoDeleteTimer() throws Exception {
|
||||
testAcceptsAcceptWithAutoDeleteTimer(MIN_AUTO_DELETE_TIMER_MS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptsAcceptWithMaxAutoDeleteTimer() throws Exception {
|
||||
testAcceptsAcceptWithAutoDeleteTimer(MAX_AUTO_DELETE_TIMER_MS);
|
||||
}
|
||||
|
||||
private void testAcceptsAcceptWithAutoDeleteTimer(@Nullable Long timer)
|
||||
throws Exception {
|
||||
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
||||
previousMsgId.getBytes(), ephemeralPublicKey.getEncoded(),
|
||||
acceptTimestamp, transportProperties, timer);
|
||||
expectParsePublicKey();
|
||||
expectParseTransportProperties();
|
||||
long autoDeleteTimer = timer == null ? NO_AUTO_DELETE_TIMER : timer;
|
||||
expectEncodeMetadata(ACCEPT, autoDeleteTimer);
|
||||
BdfMessageContext messageContext =
|
||||
validator.validateMessage(message, group, body);
|
||||
|
||||
@@ -152,7 +246,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
public void testRejectsTooLongBodyForAccept() throws Exception {
|
||||
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
||||
previousMsgId.getBytes(), ephemeralPublicKey.getEncoded(),
|
||||
acceptTimestamp, transportProperties, null);
|
||||
acceptTimestamp, transportProperties, null, null);
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
@@ -200,6 +294,40 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testRejectsAcceptWithNonLongAutoDeleteTimer()
|
||||
throws Exception {
|
||||
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
||||
previousMsgId.getBytes(), ephemeralPublicKey.getEncoded(),
|
||||
acceptTimestamp, transportProperties, "foo");
|
||||
expectParsePublicKey();
|
||||
expectParseTransportProperties();
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testRejectsAcceptWithTooSmallAutoDeleteTimer()
|
||||
throws Exception {
|
||||
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
||||
previousMsgId.getBytes(), ephemeralPublicKey.getEncoded(),
|
||||
acceptTimestamp, transportProperties,
|
||||
MIN_AUTO_DELETE_TIMER_MS - 1);
|
||||
expectParsePublicKey();
|
||||
expectParseTransportProperties();
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testRejectsAcceptWithTooBigAutoDeleteTimer() throws Exception {
|
||||
BdfList body = BdfList.of(ACCEPT.getValue(), sessionId.getBytes(),
|
||||
previousMsgId.getBytes(), ephemeralPublicKey.getEncoded(),
|
||||
acceptTimestamp, transportProperties,
|
||||
MAX_AUTO_DELETE_TIMER_MS + 1);
|
||||
expectParsePublicKey();
|
||||
expectParseTransportProperties();
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
//
|
||||
// Introduction DECLINE
|
||||
//
|
||||
@@ -209,7 +337,35 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
BdfList body = BdfList.of(DECLINE.getValue(), sessionId.getBytes(),
|
||||
previousMsgId.getBytes());
|
||||
|
||||
expectEncodeMetadata(DECLINE);
|
||||
expectEncodeMetadata(DECLINE, NO_AUTO_DELETE_TIMER);
|
||||
BdfMessageContext messageContext =
|
||||
validator.validateMessage(message, group, body);
|
||||
|
||||
assertExpectedContext(messageContext, previousMsgId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptsDeclineWithNullAutoDeleteTimer() throws Exception {
|
||||
testAcceptsDeclineWithAutoDeleteTimer(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptsDeclineWithMinAutoDeleteTimer() throws Exception {
|
||||
testAcceptsDeclineWithAutoDeleteTimer(MIN_AUTO_DELETE_TIMER_MS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptsDeclineWithMaxAutoDeleteTimer() throws Exception {
|
||||
testAcceptsDeclineWithAutoDeleteTimer(MAX_AUTO_DELETE_TIMER_MS);
|
||||
}
|
||||
|
||||
private void testAcceptsDeclineWithAutoDeleteTimer(@Nullable Long timer)
|
||||
throws Exception {
|
||||
BdfList body = BdfList.of(DECLINE.getValue(), sessionId.getBytes(),
|
||||
previousMsgId.getBytes(), timer);
|
||||
|
||||
long autoDeleteTimer = timer == null ? NO_AUTO_DELETE_TIMER : timer;
|
||||
expectEncodeMetadata(DECLINE, autoDeleteTimer);
|
||||
BdfMessageContext messageContext =
|
||||
validator.validateMessage(message, group, body);
|
||||
|
||||
@@ -225,7 +381,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
@Test(expected = FormatException.class)
|
||||
public void testRejectsTooLongBodyForDecline() throws Exception {
|
||||
BdfList body = BdfList.of(DECLINE.getValue(), sessionId.getBytes(),
|
||||
previousMsgId.getBytes(), null);
|
||||
previousMsgId.getBytes(), null, null);
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
@@ -242,6 +398,28 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testRejectsNonLongAutoDeleteTimerForDecline() throws Exception {
|
||||
BdfList body = BdfList.of(DECLINE.getValue(), sessionId.getBytes(),
|
||||
previousMsgId.getBytes(), "foo");
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testRejectsTooSmallAutoDeleteTimerForDecline()
|
||||
throws Exception {
|
||||
BdfList body = BdfList.of(DECLINE.getValue(), sessionId.getBytes(),
|
||||
previousMsgId.getBytes(), MIN_AUTO_DELETE_TIMER_MS - 1);
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testRejectsTooBigAutoDeleteTimerForDecline() throws Exception {
|
||||
BdfList body = BdfList.of(DECLINE.getValue(), sessionId.getBytes(),
|
||||
previousMsgId.getBytes(), MAX_AUTO_DELETE_TIMER_MS + 1);
|
||||
validator.validateMessage(message, group, body);
|
||||
}
|
||||
|
||||
//
|
||||
// Introduction AUTH
|
||||
//
|
||||
@@ -251,7 +429,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
BdfList body = BdfList.of(AUTH.getValue(), sessionId.getBytes(),
|
||||
previousMsgId.getBytes(), mac, signature);
|
||||
|
||||
expectEncodeMetadata(AUTH);
|
||||
expectEncodeMetadata(AUTH, NO_AUTO_DELETE_TIMER);
|
||||
BdfMessageContext messageContext =
|
||||
validator.validateMessage(message, group, body);
|
||||
|
||||
@@ -340,7 +518,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
BdfList body = BdfList.of(ACTIVATE.getValue(), sessionId.getBytes(),
|
||||
previousMsgId.getBytes(), mac);
|
||||
|
||||
expectEncodeMetadata(ACTIVATE);
|
||||
expectEncodeMetadata(ACTIVATE, NO_AUTO_DELETE_TIMER);
|
||||
BdfMessageContext messageContext =
|
||||
validator.validateMessage(message, group, body);
|
||||
|
||||
@@ -398,7 +576,7 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
BdfList body = BdfList.of(ABORT.getValue(), sessionId.getBytes(),
|
||||
previousMsgId.getBytes());
|
||||
|
||||
expectEncodeMetadata(ABORT);
|
||||
expectEncodeMetadata(ABORT, NO_AUTO_DELETE_TIMER);
|
||||
BdfMessageContext messageContext =
|
||||
validator.validateMessage(message, group, body);
|
||||
|
||||
@@ -442,17 +620,28 @@ public class IntroductionValidatorTest extends ValidatorTestCase {
|
||||
will(returnValue(ephemeralPublicKey));
|
||||
}});
|
||||
}
|
||||
private void expectEncodeRequestMetadata() {
|
||||
|
||||
private void expectParseTransportProperties() throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageEncoder).encodeRequestMetadata(message.getTimestamp());
|
||||
oneOf(clientHelper).parseAndValidateTransportPropertiesMap(
|
||||
transportProperties);
|
||||
will(returnValue(transportPropertiesMap));
|
||||
}});
|
||||
}
|
||||
|
||||
private void expectEncodeRequestMetadata(long autoDeleteTimer) {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageEncoder).encodeRequestMetadata(message.getTimestamp(),
|
||||
autoDeleteTimer);
|
||||
will(returnValue(meta));
|
||||
}});
|
||||
}
|
||||
|
||||
private void expectEncodeMetadata(MessageType type) {
|
||||
private void expectEncodeMetadata(MessageType type, long autoDeleteTimer) {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(messageEncoder).encodeMetadata(type, sessionId,
|
||||
message.getTimestamp(), false, false, false);
|
||||
message.getTimestamp(), false, false, false,
|
||||
autoDeleteTimer);
|
||||
will(returnValue(meta));
|
||||
}});
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.MAX_AUTO_DELETE_TIMER_MS;
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.MIN_AUTO_DELETE_TIMER_MS;
|
||||
import static org.briarproject.bramble.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
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.test.TestUtils.getAgreementPublicKey;
|
||||
@@ -87,8 +90,8 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||
|
||||
@Test
|
||||
public void testRequestMessageMetadata() throws FormatException {
|
||||
BdfDictionary d = messageEncoder
|
||||
.encodeRequestMetadata(timestamp);
|
||||
BdfDictionary d = messageEncoder.encodeRequestMetadata(timestamp,
|
||||
MIN_AUTO_DELETE_TIMER_MS);
|
||||
MessageMetadata meta = messageParser.parseMetadata(d);
|
||||
|
||||
assertEquals(REQUEST, meta.getMessageType());
|
||||
@@ -98,13 +101,13 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||
assertFalse(meta.isRead());
|
||||
assertFalse(meta.isVisibleInConversation());
|
||||
assertFalse(meta.isAvailableToAnswer());
|
||||
assertEquals(MIN_AUTO_DELETE_TIMER_MS, meta.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageMetadata() throws FormatException {
|
||||
BdfDictionary d = messageEncoder
|
||||
.encodeMetadata(ABORT, sessionId, timestamp, false, true,
|
||||
false);
|
||||
BdfDictionary d = messageEncoder.encodeMetadata(ABORT, sessionId,
|
||||
timestamp, false, true, false, MAX_AUTO_DELETE_TIMER_MS);
|
||||
MessageMetadata meta = messageParser.parseMetadata(d);
|
||||
|
||||
assertEquals(ABORT, meta.getMessageType());
|
||||
@@ -114,6 +117,7 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||
assertTrue(meta.isRead());
|
||||
assertFalse(meta.isVisibleInConversation());
|
||||
assertFalse(meta.isAvailableToAnswer());
|
||||
assertEquals(MAX_AUTO_DELETE_TIMER_MS, meta.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -131,6 +135,42 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||
assertEquals(previousMsgId, rm.getPreviousMessageId());
|
||||
assertEquals(author, rm.getAuthor());
|
||||
assertEquals(text, rm.getText());
|
||||
assertEquals(NO_AUTO_DELETE_TIMER, rm.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestMessageWithAutoDeleteTimer() throws FormatException {
|
||||
Message m = messageEncoder.encodeRequestMessage(groupId, timestamp,
|
||||
previousMsgId, author, text, MIN_AUTO_DELETE_TIMER_MS);
|
||||
validator.validateMessage(m, group, clientHelper.toList(m));
|
||||
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.getText());
|
||||
assertEquals(MIN_AUTO_DELETE_TIMER_MS, rm.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestMessageWithoutAutoDeleteTimer()
|
||||
throws FormatException {
|
||||
Message m = messageEncoder.encodeRequestMessage(groupId, timestamp,
|
||||
previousMsgId, author, text, NO_AUTO_DELETE_TIMER);
|
||||
validator.validateMessage(m, group, clientHelper.toList(m));
|
||||
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.getText());
|
||||
assertEquals(NO_AUTO_DELETE_TIMER, rm.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -142,6 +182,7 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||
messageParser.parseRequestMessage(m, clientHelper.toList(m));
|
||||
|
||||
assertNull(rm.getPreviousMessageId());
|
||||
assertEquals(NO_AUTO_DELETE_TIMER, rm.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -154,6 +195,7 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||
messageParser.parseRequestMessage(m, clientHelper.toList(m));
|
||||
|
||||
assertNull(rm.getText());
|
||||
assertEquals(NO_AUTO_DELETE_TIMER, rm.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -179,6 +221,57 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||
am.getEphemeralPublicKey().getEncoded());
|
||||
assertEquals(acceptTimestamp, am.getAcceptTimestamp());
|
||||
assertEquals(transportProperties, am.getTransportProperties());
|
||||
assertEquals(NO_AUTO_DELETE_TIMER, am.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptMessageWithAutoDeleteTimer() throws Exception {
|
||||
Map<TransportId, TransportProperties> transportProperties =
|
||||
getTransportPropertiesMap(2);
|
||||
|
||||
long acceptTimestamp = 1337L;
|
||||
Message m = messageEncoder.encodeAcceptMessage(groupId, timestamp,
|
||||
previousMsgId, sessionId, ephemeralPublicKey,
|
||||
acceptTimestamp, transportProperties, MAX_AUTO_DELETE_TIMER_MS);
|
||||
validator.validateMessage(m, group, clientHelper.toList(m));
|
||||
AcceptMessage am =
|
||||
messageParser.parseAcceptMessage(m, clientHelper.toList(m));
|
||||
|
||||
assertEquals(m.getId(), am.getMessageId());
|
||||
assertEquals(m.getGroupId(), am.getGroupId());
|
||||
assertEquals(m.getTimestamp(), am.getTimestamp());
|
||||
assertEquals(previousMsgId, am.getPreviousMessageId());
|
||||
assertEquals(sessionId, am.getSessionId());
|
||||
assertArrayEquals(ephemeralPublicKey.getEncoded(),
|
||||
am.getEphemeralPublicKey().getEncoded());
|
||||
assertEquals(acceptTimestamp, am.getAcceptTimestamp());
|
||||
assertEquals(transportProperties, am.getTransportProperties());
|
||||
assertEquals(MAX_AUTO_DELETE_TIMER_MS, am.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptMessageWithoutAutoDeleteTimer() throws Exception {
|
||||
Map<TransportId, TransportProperties> transportProperties =
|
||||
getTransportPropertiesMap(2);
|
||||
|
||||
long acceptTimestamp = 1337L;
|
||||
Message m = messageEncoder.encodeAcceptMessage(groupId, timestamp,
|
||||
previousMsgId, sessionId, ephemeralPublicKey,
|
||||
acceptTimestamp, transportProperties, NO_AUTO_DELETE_TIMER);
|
||||
validator.validateMessage(m, group, clientHelper.toList(m));
|
||||
AcceptMessage am =
|
||||
messageParser.parseAcceptMessage(m, clientHelper.toList(m));
|
||||
|
||||
assertEquals(m.getId(), am.getMessageId());
|
||||
assertEquals(m.getGroupId(), am.getGroupId());
|
||||
assertEquals(m.getTimestamp(), am.getTimestamp());
|
||||
assertEquals(previousMsgId, am.getPreviousMessageId());
|
||||
assertEquals(sessionId, am.getSessionId());
|
||||
assertArrayEquals(ephemeralPublicKey.getEncoded(),
|
||||
am.getEphemeralPublicKey().getEncoded());
|
||||
assertEquals(acceptTimestamp, am.getAcceptTimestamp());
|
||||
assertEquals(transportProperties, am.getTransportProperties());
|
||||
assertEquals(NO_AUTO_DELETE_TIMER, am.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -195,6 +288,39 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||
assertEquals(m.getTimestamp(), dm.getTimestamp());
|
||||
assertEquals(previousMsgId, dm.getPreviousMessageId());
|
||||
assertEquals(sessionId, dm.getSessionId());
|
||||
assertEquals(NO_AUTO_DELETE_TIMER, dm.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeclineMessageWithAutoDeleteTimer() throws Exception {
|
||||
Message m = messageEncoder.encodeDeclineMessage(groupId, timestamp,
|
||||
previousMsgId, sessionId, MIN_AUTO_DELETE_TIMER_MS);
|
||||
validator.validateMessage(m, group, clientHelper.toList(m));
|
||||
DeclineMessage dm =
|
||||
messageParser.parseDeclineMessage(m, clientHelper.toList(m));
|
||||
|
||||
assertEquals(m.getId(), dm.getMessageId());
|
||||
assertEquals(m.getGroupId(), dm.getGroupId());
|
||||
assertEquals(m.getTimestamp(), dm.getTimestamp());
|
||||
assertEquals(previousMsgId, dm.getPreviousMessageId());
|
||||
assertEquals(sessionId, dm.getSessionId());
|
||||
assertEquals(MIN_AUTO_DELETE_TIMER_MS, dm.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeclineMessageWithoutAutoDeleteTimer() throws Exception {
|
||||
Message m = messageEncoder.encodeDeclineMessage(groupId, timestamp,
|
||||
previousMsgId, sessionId, NO_AUTO_DELETE_TIMER);
|
||||
validator.validateMessage(m, group, clientHelper.toList(m));
|
||||
DeclineMessage dm =
|
||||
messageParser.parseDeclineMessage(m, clientHelper.toList(m));
|
||||
|
||||
assertEquals(m.getId(), dm.getMessageId());
|
||||
assertEquals(m.getGroupId(), dm.getGroupId());
|
||||
assertEquals(m.getTimestamp(), dm.getTimestamp());
|
||||
assertEquals(previousMsgId, dm.getPreviousMessageId());
|
||||
assertEquals(sessionId, dm.getSessionId());
|
||||
assertEquals(NO_AUTO_DELETE_TIMER, dm.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -213,6 +339,7 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||
assertEquals(sessionId, am.getSessionId());
|
||||
assertArrayEquals(mac, am.getMac());
|
||||
assertArrayEquals(signature, am.getSignature());
|
||||
assertEquals(NO_AUTO_DELETE_TIMER, am.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -230,6 +357,7 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||
assertEquals(previousMsgId, am.getPreviousMessageId());
|
||||
assertEquals(sessionId, am.getSessionId());
|
||||
assertArrayEquals(mac, am.getMac());
|
||||
assertEquals(NO_AUTO_DELETE_TIMER, am.getAutoDeleteTimer());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -246,5 +374,6 @@ public class MessageEncoderParserIntegrationTest extends BrambleTestCase {
|
||||
assertEquals(m.getTimestamp(), am.getTimestamp());
|
||||
assertEquals(previousMsgId, am.getPreviousMessageId());
|
||||
assertEquals(sessionId, am.getSessionId());
|
||||
assertEquals(NO_AUTO_DELETE_TIMER, am.getAutoDeleteTimer());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,8 @@ internal class WebSocketControllerTest : ControllerTest() {
|
||||
author,
|
||||
text,
|
||||
false,
|
||||
AuthorInfo(VERIFIED)
|
||||
AuthorInfo(VERIFIED),
|
||||
NO_AUTO_DELETE_TIMER
|
||||
)
|
||||
val introductionRequestEvent =
|
||||
IntroductionRequestReceivedEvent(introductionRequest, contact.id)
|
||||
|
||||
@@ -89,7 +89,7 @@ internal class MessagingControllerImplTest : ControllerTest() {
|
||||
fun listIntroductionRequest() {
|
||||
val request = IntroductionRequest(
|
||||
message.id, group.id, timestamp, true, true, true, false, sessionId, author, text,
|
||||
false, AuthorInfo(UNVERIFIED)
|
||||
false, AuthorInfo(UNVERIFIED), NO_AUTO_DELETE_TIMER
|
||||
)
|
||||
|
||||
expectGetContact()
|
||||
@@ -330,7 +330,7 @@ internal class MessagingControllerImplTest : ControllerTest() {
|
||||
fun testIntroductionRequestWithNullText() {
|
||||
val request = IntroductionRequest(
|
||||
message.id, group.id, timestamp, true, true, true, false, sessionId, author, null,
|
||||
false, AuthorInfo(VERIFIED)
|
||||
false, AuthorInfo(VERIFIED), NO_AUTO_DELETE_TIMER
|
||||
)
|
||||
val json = """
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user