From d4b87983e81dd3b739c4b85083b2c7d5d02a84d2 Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Thu, 19 Apr 2018 16:40:44 +0100 Subject: [PATCH] Avoid an unnecessary copy when parsing messages. --- .../bramble/api/sync/MessageFactory.java | 2 + .../bramble/sync/GroupFactoryImpl.java | 5 ++- .../bramble/sync/MessageFactoryImpl.java | 38 +++++++++++++++---- .../bramble/sync/SyncRecordReaderImpl.java | 14 +------ 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageFactory.java b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageFactory.java index e85b15d7df..a31e773700 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageFactory.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/sync/MessageFactory.java @@ -7,5 +7,7 @@ public interface MessageFactory { Message createMessage(GroupId g, long timestamp, byte[] body); + Message createMessage(byte[] raw); + Message createMessage(MessageId m, byte[] raw); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/GroupFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/GroupFactoryImpl.java index 5a46a4aad5..0e34cf6b4d 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/GroupFactoryImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/GroupFactoryImpl.java @@ -20,6 +20,9 @@ import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES; @NotNullByDefault class GroupFactoryImpl implements GroupFactory { + private static final byte[] FORMAT_VERSION_BYTES = + new byte[] {FORMAT_VERSION}; + private final CryptoComponent crypto; @Inject @@ -31,7 +34,7 @@ class GroupFactoryImpl implements GroupFactory { public Group createGroup(ClientId c, int majorVersion, byte[] descriptor) { byte[] majorVersionBytes = new byte[INT_32_BYTES]; ByteUtils.writeUint32(majorVersion, majorVersionBytes, 0); - byte[] hash = crypto.hash(LABEL, new byte[] {FORMAT_VERSION}, + byte[] hash = crypto.hash(LABEL, FORMAT_VERSION_BYTES, StringUtils.toUtf8(c.getString()), majorVersionBytes, descriptor); return new Group(new GroupId(hash), c, majorVersion, descriptor); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/MessageFactoryImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/MessageFactoryImpl.java index 8e8151079f..754f0edac5 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/MessageFactoryImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/MessageFactoryImpl.java @@ -24,6 +24,9 @@ import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES; @NotNullByDefault class MessageFactoryImpl implements MessageFactory { + private static final byte[] FORMAT_VERSION_BYTES = + new byte[] {FORMAT_VERSION}; + private final CryptoComponent crypto; @Inject @@ -35,14 +38,7 @@ class MessageFactoryImpl implements MessageFactory { public Message createMessage(GroupId g, long timestamp, byte[] body) { if (body.length > MAX_MESSAGE_BODY_LENGTH) throw new IllegalArgumentException(); - byte[] versionBytes = new byte[] {FORMAT_VERSION}; - // There's only one block, so the root hash is the hash of the block - byte[] rootHash = crypto.hash(BLOCK_LABEL, versionBytes, body); - byte[] timeBytes = new byte[INT_64_BYTES]; - ByteUtils.writeUint64(timestamp, timeBytes, 0); - byte[] idHash = crypto.hash(ID_LABEL, versionBytes, g.getBytes(), - timeBytes, rootHash); - MessageId id = new MessageId(idHash); + MessageId id = getMessageId(g, timestamp, body); byte[] raw = new byte[MESSAGE_HEADER_LENGTH + body.length]; System.arraycopy(g.getBytes(), 0, raw, 0, UniqueId.LENGTH); ByteUtils.writeUint64(timestamp, raw, UniqueId.LENGTH); @@ -50,6 +46,32 @@ class MessageFactoryImpl implements MessageFactory { return new Message(id, g, timestamp, raw); } + private MessageId getMessageId(GroupId g, long timestamp, byte[] body) { + // There's only one block, so the root hash is the hash of the block + byte[] rootHash = crypto.hash(BLOCK_LABEL, FORMAT_VERSION_BYTES, body); + byte[] timeBytes = new byte[INT_64_BYTES]; + ByteUtils.writeUint64(timestamp, timeBytes, 0); + byte[] idHash = crypto.hash(ID_LABEL, FORMAT_VERSION_BYTES, + g.getBytes(), timeBytes, rootHash); + return new MessageId(idHash); + } + + @Override + public Message createMessage(byte[] raw) { + if (raw.length < MESSAGE_HEADER_LENGTH) + throw new IllegalArgumentException(); + if (raw.length > MAX_MESSAGE_LENGTH) + throw new IllegalArgumentException(); + byte[] groupId = new byte[UniqueId.LENGTH]; + System.arraycopy(raw, 0, groupId, 0, UniqueId.LENGTH); + GroupId g = new GroupId(groupId); + long timestamp = ByteUtils.readUint64(raw, UniqueId.LENGTH); + byte[] body = new byte[raw.length - MESSAGE_HEADER_LENGTH]; + System.arraycopy(raw, MESSAGE_HEADER_LENGTH, body, 0, body.length); + MessageId id = getMessageId(g, timestamp, body); + return new Message(id, g, timestamp, raw); + } + @Override public Message createMessage(MessageId m, byte[] raw) { if (raw.length < MESSAGE_HEADER_LENGTH) diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordReaderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordReaderImpl.java index d7566979d2..3a7c6d057b 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordReaderImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/SyncRecordReaderImpl.java @@ -6,7 +6,6 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.record.Record; import org.briarproject.bramble.api.record.RecordReader; import org.briarproject.bramble.api.sync.Ack; -import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.MessageFactory; import org.briarproject.bramble.api.sync.MessageId; @@ -126,20 +125,11 @@ class SyncRecordReaderImpl implements SyncRecordReader { assert nextRecord != null; byte[] payload = nextRecord.getPayload(); if (payload.length < MESSAGE_HEADER_LENGTH) throw new FormatException(); - // Group ID - byte[] id = new byte[UniqueId.LENGTH]; - System.arraycopy(payload, 0, id, 0, UniqueId.LENGTH); - GroupId groupId = new GroupId(id); - // Timestamp + // Validate timestamp long timestamp = ByteUtils.readUint64(payload, UniqueId.LENGTH); if (timestamp < 0) throw new FormatException(); - // Body - byte[] body = new byte[payload.length - MESSAGE_HEADER_LENGTH]; - System.arraycopy(payload, MESSAGE_HEADER_LENGTH, body, 0, - payload.length - MESSAGE_HEADER_LENGTH); nextRecord = null; - // TODO: Add a method that reuses the raw message - return messageFactory.createMessage(groupId, timestamp, body); + return messageFactory.createMessage(payload); } @Override -- GitLab