diff --git a/exonum-java-binding-core/src/main/java/com/exonum/binding/messages/BinaryMessageBuilder.java b/exonum-java-binding-core/src/main/java/com/exonum/binding/messages/BinaryMessageBuilder.java index 54e0b2a2e9..c398a21600 100644 --- a/exonum-java-binding-core/src/main/java/com/exonum/binding/messages/BinaryMessageBuilder.java +++ b/exonum-java-binding-core/src/main/java/com/exonum/binding/messages/BinaryMessageBuilder.java @@ -1,9 +1,9 @@ package com.exonum.binding.messages; -import static com.exonum.binding.messages.Message.BODY_LENGTH_OFFSET; import static com.exonum.binding.messages.Message.BODY_OFFSET; import static com.exonum.binding.messages.Message.MESSAGE_TYPE_OFFSET; import static com.exonum.binding.messages.Message.NET_ID_OFFSET; +import static com.exonum.binding.messages.Message.PAYLOAD_LENGTH_OFFSET; import static com.exonum.binding.messages.Message.SERVICE_ID_OFFSET; import static com.exonum.binding.messages.Message.VERSION_OFFSET; import static com.google.common.base.Preconditions.checkNotNull; @@ -62,7 +62,7 @@ private void putHeader(ByteBuffer buffer) { .put(VERSION_OFFSET, message.getVersion()) .putShort(SERVICE_ID_OFFSET, message.getServiceId()) .putShort(MESSAGE_TYPE_OFFSET, message.getMessageType()) - .putInt(BODY_LENGTH_OFFSET, message.getBody().remaining()); + .putInt(PAYLOAD_LENGTH_OFFSET, message.size()); } private void putBody(ByteBuffer buffer) { diff --git a/exonum-java-binding-core/src/main/java/com/exonum/binding/messages/Message.java b/exonum-java-binding-core/src/main/java/com/exonum/binding/messages/Message.java index fa708c0eb1..6186582d22 100644 --- a/exonum-java-binding-core/src/main/java/com/exonum/binding/messages/Message.java +++ b/exonum-java-binding-core/src/main/java/com/exonum/binding/messages/Message.java @@ -13,7 +13,7 @@ public interface Message { int VERSION_OFFSET = 1; int MESSAGE_TYPE_OFFSET = 2; int SERVICE_ID_OFFSET = 4; - int BODY_LENGTH_OFFSET = 6; + int PAYLOAD_LENGTH_OFFSET = 6; int HEADER_SIZE = 10; int BODY_OFFSET = HEADER_SIZE; int SIGNATURE_SIZE = 64; diff --git a/exonum-java-binding-core/src/main/java/com/exonum/binding/messages/MessageReader.java b/exonum-java-binding-core/src/main/java/com/exonum/binding/messages/MessageReader.java index 78f5e60548..308de0d74c 100644 --- a/exonum-java-binding-core/src/main/java/com/exonum/binding/messages/MessageReader.java +++ b/exonum-java-binding-core/src/main/java/com/exonum/binding/messages/MessageReader.java @@ -30,11 +30,13 @@ public static MessageReader wrap(ByteBuffer buffer) { int bufferSize = buffer.limit(); checkArgument(MIN_MESSAGE_BUFFER_SIZE <= bufferSize, - "The buffer size (%s) is less than the minimal possible (%s)", + "The buffer size (%s) is less than the minimal possible message size (%s)", bufferSize, MIN_MESSAGE_BUFFER_SIZE); - int expectedSize = Message.messageSize(reader.bodySize()); + // Check the 'payload_length' field of the message matches the actual buffer size. + int expectedSize = reader.size(); checkArgument(bufferSize == expectedSize, - "The size of the buffer (%s) does not match expected (%s)", bufferSize, expectedSize); + "The size of the buffer (%s) does not match the expected size " + + "specified in the message header (%s)", bufferSize, expectedSize); return reader; } @@ -84,7 +86,7 @@ public ByteBuffer getBody() { } private int bodySize() { - return message.getInt(BODY_LENGTH_OFFSET); + return size() - HEADER_SIZE - SIGNATURE_SIZE; } /** @@ -101,7 +103,7 @@ public ByteBuffer getSignature() { @Override public int size() { - return message.limit(); + return message.getInt(PAYLOAD_LENGTH_OFFSET); } /** diff --git a/exonum-java-binding-core/src/test/java/com/exonum/binding/messages/MessageReaderTest.java b/exonum-java-binding-core/src/test/java/com/exonum/binding/messages/MessageReaderTest.java index 29231a1596..36145999d3 100644 --- a/exonum-java-binding-core/src/test/java/com/exonum/binding/messages/MessageReaderTest.java +++ b/exonum-java-binding-core/src/test/java/com/exonum/binding/messages/MessageReaderTest.java @@ -1,10 +1,10 @@ package com.exonum.binding.messages; import static com.exonum.binding.messages.ByteBufferAllocator.allocateBuffer; -import static com.exonum.binding.messages.Message.BODY_LENGTH_OFFSET; import static com.exonum.binding.messages.Message.BODY_OFFSET; import static com.exonum.binding.messages.Message.MESSAGE_TYPE_OFFSET; import static com.exonum.binding.messages.Message.NET_ID_OFFSET; +import static com.exonum.binding.messages.Message.PAYLOAD_LENGTH_OFFSET; import static com.exonum.binding.messages.Message.SERVICE_ID_OFFSET; import static com.exonum.binding.messages.Message.SIGNATURE_SIZE; import static com.exonum.binding.messages.Message.VERSION_OFFSET; @@ -29,7 +29,8 @@ public class MessageReaderTest { public void wrapThrowsIfTooSmall() throws Exception { ByteBuffer buf = allocateBuffer(2); - expectedException.expectMessage("The buffer size (2) is less than the minimal possible (74)"); + expectedException.expectMessage("The buffer size (2) is less than the minimal possible " + + "message size (74)"); expectedException.expect(IllegalArgumentException.class); MessageReader.wrap(buf); } @@ -38,14 +39,25 @@ public void wrapThrowsIfTooSmall() throws Exception { public void wrapThrowsIfTooSmall2() throws Exception { ByteBuffer buf = allocateBuffer(MIN_MESSAGE_BUFFER_SIZE - 1); - expectedException.expectMessage("The buffer size (73) is less than the minimal possible (74)"); + expectedException.expectMessage("The buffer size (73) is less than the minimal possible " + + "message size (74)"); + expectedException.expect(IllegalArgumentException.class); + MessageReader.wrap(buf); + } + + @Test + public void wrapThrowsIfTooSmallWithSetMessageSize() throws Exception { + ByteBuffer buf = allocateMessageBuffer(MIN_MESSAGE_BUFFER_SIZE - 1); + + expectedException.expectMessage("The buffer size (73) is less than the minimal possible " + + "message size (74)"); expectedException.expect(IllegalArgumentException.class); MessageReader.wrap(buf); } @Test public void wrapsMinimalMessage() throws Exception { - ByteBuffer buf = allocateBuffer(MIN_MESSAGE_BUFFER_SIZE); + ByteBuffer buf = allocateMessageBuffer(MIN_MESSAGE_BUFFER_SIZE); MessageReader m = MessageReader.wrap(buf); @@ -54,7 +66,8 @@ public void wrapsMinimalMessage() throws Exception { @Test public void wrapsWhenLimitNotEqualCapacity() throws Exception { - ByteBuffer buf = allocateBuffer(2 * MIN_MESSAGE_BUFFER_SIZE); + ByteBuffer buf = allocateBuffer(2 * MIN_MESSAGE_BUFFER_SIZE) + .putInt(PAYLOAD_LENGTH_OFFSET, MIN_MESSAGE_BUFFER_SIZE); buf.limit(MIN_MESSAGE_BUFFER_SIZE); MessageReader m = MessageReader.wrap(buf); @@ -63,15 +76,29 @@ public void wrapsWhenLimitNotEqualCapacity() throws Exception { } @Test - public void wrapThrowsIfBodySizeFieldDoesNotMatchActual() throws Exception { + public void wrapThrowsIfMessageSizeFieldGreaterThanActual() throws Exception { int bufferSize = MIN_MESSAGE_BUFFER_SIZE; ByteBuffer buf = allocateBuffer(bufferSize); - int bodySize = 2048; - buf.putInt(BODY_LENGTH_OFFSET, bodySize); + int messageSize = 2048; + buf.putInt(PAYLOAD_LENGTH_OFFSET, messageSize); - int expectedBufferSize = Message.messageSize(bodySize); expectedException.expectMessage("The size of the buffer (" + bufferSize - + ") does not match expected (" + expectedBufferSize + ")"); + + ") does not match the expected size specified in the message header (" + messageSize + + ")"); + expectedException.expect(IllegalArgumentException.class); + MessageReader.wrap(buf); + } + + @Test + public void wrapThrowsIfMessageSizeFieldLessThanActual() throws Exception { + int bufferSize = 2 * MIN_MESSAGE_BUFFER_SIZE; + ByteBuffer buf = allocateBuffer(bufferSize); + int messageSize = bufferSize - 1; + buf.putInt(PAYLOAD_LENGTH_OFFSET, messageSize); + + expectedException.expectMessage("The size of the buffer (" + bufferSize + + ") does not match the expected size specified in the message header (" + messageSize + + ")"); expectedException.expect(IllegalArgumentException.class); MessageReader.wrap(buf); } @@ -79,7 +106,7 @@ public void wrapThrowsIfBodySizeFieldDoesNotMatchActual() throws Exception { @Test public void getNetworkId() throws Exception { byte netId = 0x01; - ByteBuffer buf = allocateBuffer(MIN_MESSAGE_BUFFER_SIZE) + ByteBuffer buf = allocateMessageBuffer(MIN_MESSAGE_BUFFER_SIZE) .put(NET_ID_OFFSET, netId); MessageReader m = MessageReader.wrap(buf); @@ -90,7 +117,7 @@ public void getNetworkId() throws Exception { @Test public void getVersion() throws Exception { byte version = 0x02; - ByteBuffer buf = allocateBuffer(MIN_MESSAGE_BUFFER_SIZE) + ByteBuffer buf = allocateMessageBuffer(MIN_MESSAGE_BUFFER_SIZE) .put(VERSION_OFFSET, version); MessageReader m = MessageReader.wrap(buf); @@ -101,7 +128,7 @@ public void getVersion() throws Exception { @Test public void getServiceId() throws Exception { short serviceId = 0x0BCD; - ByteBuffer buf = allocateBuffer(MIN_MESSAGE_BUFFER_SIZE) + ByteBuffer buf = allocateMessageBuffer(MIN_MESSAGE_BUFFER_SIZE) .putShort(SERVICE_ID_OFFSET, serviceId); MessageReader m = MessageReader.wrap(buf); @@ -112,7 +139,7 @@ public void getServiceId() throws Exception { @Test public void getMessageType() throws Exception { short messageType = 0x0BCD; - ByteBuffer buf = allocateBuffer(MIN_MESSAGE_BUFFER_SIZE) + ByteBuffer buf = allocateMessageBuffer(MIN_MESSAGE_BUFFER_SIZE) .putShort(MESSAGE_TYPE_OFFSET, messageType); MessageReader m = MessageReader.wrap(buf); @@ -122,7 +149,7 @@ public void getMessageType() throws Exception { @Test public void getBody_Empty() throws Exception { - ByteBuffer buf = allocateBuffer(MIN_MESSAGE_BUFFER_SIZE); + ByteBuffer buf = allocateMessageBuffer(MIN_MESSAGE_BUFFER_SIZE); boolean directBuffer = buf.isDirect(); MessageReader m = MessageReader.wrap(buf); @@ -136,8 +163,7 @@ public void getBody_Empty() throws Exception { public void getBody_4Bytes() throws Exception { int bodySize = Integer.BYTES; int bodyValue = 0x12345678; - ByteBuffer buf = allocateBuffer(MIN_MESSAGE_BUFFER_SIZE + bodySize) - .putInt(BODY_LENGTH_OFFSET, bodySize) + ByteBuffer buf = allocateMessageBuffer(MIN_MESSAGE_BUFFER_SIZE + bodySize) .putInt(BODY_OFFSET, bodyValue); MessageReader m = MessageReader.wrap(buf); @@ -151,7 +177,7 @@ public void getBody_4Bytes() throws Exception { @Test public void getSignature() throws Exception { byte[] signature = createPrefixed(bytes("Signature bytes"), SIGNATURE_SIZE); - ByteBuffer buf = allocateBuffer(MIN_MESSAGE_BUFFER_SIZE); + ByteBuffer buf = allocateMessageBuffer(MIN_MESSAGE_BUFFER_SIZE); buf.position(MIN_MESSAGE_BUFFER_SIZE - SIGNATURE_SIZE); buf.put(signature); buf.flip(); @@ -163,7 +189,7 @@ public void getSignature() throws Exception { @Test public void getMessage() throws Exception { - ByteBuffer buf = allocateBuffer(MIN_MESSAGE_BUFFER_SIZE) + ByteBuffer buf = allocateMessageBuffer(MIN_MESSAGE_BUFFER_SIZE) .put(NET_ID_OFFSET, (byte) 0x02) .put(VERSION_OFFSET, (byte) 0x01) .putShort(MESSAGE_TYPE_OFFSET, (short) 0x0ABC); @@ -177,10 +203,18 @@ public void getMessage() throws Exception { @Test public void size() throws Exception { int bufferSize = MIN_MESSAGE_BUFFER_SIZE; - ByteBuffer buf = allocateBuffer(bufferSize); + ByteBuffer buf = allocateMessageBuffer(bufferSize); MessageReader m = MessageReader.wrap(buf); assertThat(m.size(), equalTo(bufferSize)); } + + /** + * Allocates a byte buffer of the given size and sets its "payload_length" field. + */ + private static ByteBuffer allocateMessageBuffer(int bufferSize) { + return allocateBuffer(bufferSize) + .putInt(PAYLOAD_LENGTH_OFFSET, bufferSize); + } }