mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 19:29:06 +01:00
Merge branch '382-message-dependencies' into 'master'
Introduce a MessageContext class to be used by all validators This change will allow to pass message dependencies from the client validators to the `ValidationManager`. Please see my thoughts in #382 for more details. See merge request !197
This commit is contained in:
@@ -4,13 +4,16 @@ import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.clients.MessageQueueManager.QueueMessageValidator;
|
||||
import org.briarproject.api.clients.QueueMessage;
|
||||
import org.briarproject.api.clients.BdfMessageContext;
|
||||
import org.briarproject.api.data.BdfDictionary;
|
||||
import org.briarproject.api.data.BdfList;
|
||||
import org.briarproject.api.data.MetadataEncoder;
|
||||
import org.briarproject.api.db.Metadata;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.InvalidMessageException;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.ValidationManager.MessageValidator;
|
||||
import org.briarproject.api.sync.MessageContext;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
@@ -37,43 +40,41 @@ public abstract class BdfMessageValidator implements MessageValidator,
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
protected abstract BdfDictionary validateMessage(Message m, Group g,
|
||||
BdfList body) throws FormatException;
|
||||
protected abstract BdfMessageContext validateMessage(Message m, Group g,
|
||||
BdfList body) throws InvalidMessageException, FormatException;
|
||||
|
||||
@Override
|
||||
public Metadata validateMessage(Message m, Group g) {
|
||||
public MessageContext validateMessage(Message m, Group g)
|
||||
throws InvalidMessageException {
|
||||
return validateMessage(m, g, MESSAGE_HEADER_LENGTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metadata validateMessage(QueueMessage q, Group g) {
|
||||
public MessageContext validateMessage(QueueMessage q, Group g)
|
||||
throws InvalidMessageException {
|
||||
return validateMessage(q, g, QUEUE_MESSAGE_HEADER_LENGTH);
|
||||
}
|
||||
|
||||
private Metadata validateMessage(Message m, Group g, int headerLength) {
|
||||
private MessageContext validateMessage(Message m, Group g, int headerLength)
|
||||
throws InvalidMessageException {
|
||||
// Reject the message if it's too far in the future
|
||||
long now = clock.currentTimeMillis();
|
||||
if (m.getTimestamp() - now > MAX_CLOCK_DIFFERENCE) {
|
||||
LOG.info("Timestamp is too far in the future");
|
||||
return null;
|
||||
throw new InvalidMessageException(
|
||||
"Timestamp is too far in the future");
|
||||
}
|
||||
byte[] raw = m.getRaw();
|
||||
if (raw.length <= headerLength) {
|
||||
LOG.info("Message is too short");
|
||||
return null;
|
||||
throw new InvalidMessageException("Message is too short");
|
||||
}
|
||||
try {
|
||||
BdfList body = clientHelper.toList(raw, headerLength,
|
||||
raw.length - headerLength);
|
||||
BdfDictionary meta = validateMessage(m, g, body);
|
||||
if (meta == null) {
|
||||
LOG.info("Invalid message");
|
||||
return null;
|
||||
}
|
||||
return metadataEncoder.encode(meta);
|
||||
BdfMessageContext result = validateMessage(m, g, body);
|
||||
Metadata meta = metadataEncoder.encode(result.getDictionary());
|
||||
return new MessageContext(meta, result.getDependencies());
|
||||
} catch (FormatException e) {
|
||||
LOG.info("Invalid message");
|
||||
return null;
|
||||
throw new InvalidMessageException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,12 @@ import org.briarproject.api.db.Transaction;
|
||||
import org.briarproject.api.sync.ClientId;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.InvalidMessageException;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.briarproject.api.sync.ValidationManager;
|
||||
import org.briarproject.api.sync.ValidationManager.IncomingMessageHook;
|
||||
import org.briarproject.api.sync.MessageContext;
|
||||
import org.briarproject.util.ByteUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -169,7 +171,8 @@ class MessageQueueManagerImpl implements MessageQueueManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metadata validateMessage(Message m, Group g) {
|
||||
public MessageContext validateMessage(Message m, Group g)
|
||||
throws InvalidMessageException {
|
||||
byte[] raw = m.getRaw();
|
||||
if (raw.length < QUEUE_MESSAGE_HEADER_LENGTH) return null;
|
||||
long queuePosition = ByteUtils.readUint64(raw,
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.forum;
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.UniqueId;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.clients.BdfMessageContext;
|
||||
import org.briarproject.api.crypto.CryptoComponent;
|
||||
import org.briarproject.api.crypto.KeyParser;
|
||||
import org.briarproject.api.crypto.PublicKey;
|
||||
@@ -13,6 +14,7 @@ import org.briarproject.api.data.MetadataEncoder;
|
||||
import org.briarproject.api.identity.Author;
|
||||
import org.briarproject.api.identity.AuthorFactory;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.InvalidMessageException;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.system.Clock;
|
||||
import org.briarproject.clients.BdfMessageValidator;
|
||||
@@ -39,8 +41,8 @@ class ForumPostValidator extends BdfMessageValidator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BdfDictionary validateMessage(Message m, Group g,
|
||||
BdfList body) throws FormatException {
|
||||
protected BdfMessageContext validateMessage(Message m, Group g,
|
||||
BdfList body) throws InvalidMessageException, FormatException {
|
||||
// Parent ID, author, content type, forum post body, signature
|
||||
checkSize(body, 5);
|
||||
// Parent ID is optional
|
||||
@@ -69,12 +71,10 @@ class ForumPostValidator extends BdfMessageValidator {
|
||||
checkLength(sig, 0, MAX_SIGNATURE_LENGTH);
|
||||
// If there's an author there must be a signature and vice versa
|
||||
if (author != null && sig == null) {
|
||||
LOG.info("Author without signature");
|
||||
return null;
|
||||
throw new InvalidMessageException("Author without signature");
|
||||
}
|
||||
if (author == null && sig != null) {
|
||||
LOG.info("Signature without author");
|
||||
return null;
|
||||
throw new InvalidMessageException("Signature without author");
|
||||
}
|
||||
// Verify the signature, if any
|
||||
if (author != null) {
|
||||
@@ -90,12 +90,10 @@ class ForumPostValidator extends BdfMessageValidator {
|
||||
signature.initVerify(key);
|
||||
signature.update(clientHelper.toByteArray(signed));
|
||||
if (!signature.verify(sig)) {
|
||||
LOG.info("Invalid signature");
|
||||
return null;
|
||||
throw new InvalidMessageException("Invalid signature");
|
||||
}
|
||||
} catch (GeneralSecurityException e) {
|
||||
LOG.info("Invalid public key");
|
||||
return null;
|
||||
throw new InvalidMessageException("Invalid public key");
|
||||
}
|
||||
}
|
||||
// Return the metadata
|
||||
@@ -111,6 +109,6 @@ class ForumPostValidator extends BdfMessageValidator {
|
||||
}
|
||||
meta.put("contentType", contentType);
|
||||
meta.put("read", false);
|
||||
return meta;
|
||||
return new BdfMessageContext(meta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.forum;
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.clients.SessionId;
|
||||
import org.briarproject.api.clients.BdfMessageContext;
|
||||
import org.briarproject.api.data.BdfDictionary;
|
||||
import org.briarproject.api.data.BdfList;
|
||||
import org.briarproject.api.data.MetadataEncoder;
|
||||
@@ -36,7 +37,7 @@ class ForumSharingValidator extends BdfMessageValidator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BdfDictionary validateMessage(Message m, Group g,
|
||||
protected BdfMessageContext validateMessage(Message m, Group g,
|
||||
BdfList body) throws FormatException {
|
||||
|
||||
BdfDictionary d = new BdfDictionary();
|
||||
@@ -75,6 +76,6 @@ class ForumSharingValidator extends BdfMessageValidator {
|
||||
d.put(SESSION_ID, id);
|
||||
d.put(LOCAL, false);
|
||||
d.put(TIME, m.getTimestamp());
|
||||
return d;
|
||||
return new BdfMessageContext(d);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,11 @@ package org.briarproject.introduction;
|
||||
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.clients.SessionId;
|
||||
import org.briarproject.api.clients.BdfMessageContext;
|
||||
import org.briarproject.api.data.BdfDictionary;
|
||||
import org.briarproject.api.data.BdfList;
|
||||
import org.briarproject.api.data.MetadataEncoder;
|
||||
import org.briarproject.api.clients.SessionId;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.system.Clock;
|
||||
@@ -42,7 +43,7 @@ class IntroductionValidator extends BdfMessageValidator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BdfDictionary validateMessage(Message m, Group g, BdfList body)
|
||||
protected BdfMessageContext validateMessage(Message m, Group g, BdfList body)
|
||||
throws FormatException {
|
||||
|
||||
BdfDictionary d;
|
||||
@@ -67,7 +68,7 @@ class IntroductionValidator extends BdfMessageValidator {
|
||||
d.put(GROUP_ID, m.getGroupId());
|
||||
d.put(MESSAGE_ID, m.getId());
|
||||
d.put(MESSAGE_TIME, m.getTimestamp());
|
||||
return d;
|
||||
return new BdfMessageContext(d);
|
||||
}
|
||||
|
||||
private BdfDictionary validateRequest(BdfList message)
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.messaging;
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.UniqueId;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.clients.BdfMessageContext;
|
||||
import org.briarproject.api.data.BdfDictionary;
|
||||
import org.briarproject.api.data.BdfList;
|
||||
import org.briarproject.api.data.MetadataEncoder;
|
||||
@@ -22,7 +23,7 @@ class PrivateMessageValidator extends BdfMessageValidator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BdfDictionary validateMessage(Message m, Group g,
|
||||
protected BdfMessageContext validateMessage(Message m, Group g,
|
||||
BdfList body) throws FormatException {
|
||||
// Parent ID, content type, private message body
|
||||
checkSize(body, 3);
|
||||
@@ -42,6 +43,6 @@ class PrivateMessageValidator extends BdfMessageValidator {
|
||||
meta.put("contentType", contentType);
|
||||
meta.put("local", false);
|
||||
meta.put("read", false);
|
||||
return meta;
|
||||
return new BdfMessageContext(meta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.briarproject.properties;
|
||||
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.clients.ClientHelper;
|
||||
import org.briarproject.api.clients.BdfMessageContext;
|
||||
import org.briarproject.api.data.BdfDictionary;
|
||||
import org.briarproject.api.data.BdfList;
|
||||
import org.briarproject.api.data.MetadataEncoder;
|
||||
@@ -22,7 +23,7 @@ public class TransportPropertyValidator extends BdfMessageValidator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BdfDictionary validateMessage(Message m, Group g,
|
||||
protected BdfMessageContext validateMessage(Message m, Group g,
|
||||
BdfList body) throws FormatException {
|
||||
// Transport ID, version, properties
|
||||
checkSize(body, 3);
|
||||
@@ -45,6 +46,6 @@ public class TransportPropertyValidator extends BdfMessageValidator {
|
||||
meta.put("transportId", transportId);
|
||||
meta.put("version", version);
|
||||
meta.put("local", false);
|
||||
return meta;
|
||||
return new BdfMessageContext(meta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,11 @@ import org.briarproject.api.lifecycle.Service;
|
||||
import org.briarproject.api.sync.ClientId;
|
||||
import org.briarproject.api.sync.Group;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.briarproject.api.sync.InvalidMessageException;
|
||||
import org.briarproject.api.sync.Message;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
import org.briarproject.api.sync.ValidationManager;
|
||||
import org.briarproject.api.sync.MessageContext;
|
||||
import org.briarproject.util.ByteUtils;
|
||||
|
||||
import java.util.LinkedList;
|
||||
@@ -31,6 +33,7 @@ import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
|
||||
|
||||
@@ -152,31 +155,54 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
if (v == null) {
|
||||
LOG.warning("No validator");
|
||||
} else {
|
||||
Metadata meta = v.validateMessage(m, g);
|
||||
storeValidationResult(m, g.getClientId(), meta);
|
||||
try {
|
||||
MessageContext context = v.validateMessage(m, g);
|
||||
storeMessageContext(m, g.getClientId(), context);
|
||||
} catch (InvalidMessageException e) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.log(INFO, e.toString(), e);
|
||||
markMessageInvalid(m, g.getClientId());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void storeValidationResult(final Message m, final ClientId c,
|
||||
final Metadata meta) {
|
||||
private void storeMessageContext(final Message m, final ClientId c,
|
||||
final MessageContext result) {
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
if (meta == null) {
|
||||
db.setMessageValid(txn, m, c, false);
|
||||
} else {
|
||||
db.mergeMessageMetadata(txn, m.getId(), meta);
|
||||
db.setMessageValid(txn, m, c, true);
|
||||
db.setMessageShared(txn, m, true);
|
||||
IncomingMessageHook hook = hooks.get(c);
|
||||
if (hook != null)
|
||||
hook.incomingMessage(txn, m, meta);
|
||||
}
|
||||
Metadata meta = result.getMetadata();
|
||||
db.mergeMessageMetadata(txn, m.getId(), meta);
|
||||
db.setMessageValid(txn, m, c, true);
|
||||
db.setMessageShared(txn, m, true);
|
||||
IncomingMessageHook hook = hooks.get(c);
|
||||
if (hook != null)
|
||||
hook.incomingMessage(txn, m, meta);
|
||||
txn.setComplete();
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void markMessageInvalid(final Message m, final ClientId c) {
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.setMessageValid(txn, m, c, false);
|
||||
txn.setComplete();
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
|
||||
Reference in New Issue
Block a user