diff --git a/src/zutil/net/mqtt/packet/MqttPacketPublish.java b/src/zutil/net/mqtt/packet/MqttPacketPublish.java index 6432148..c67e026 100755 --- a/src/zutil/net/mqtt/packet/MqttPacketPublish.java +++ b/src/zutil/net/mqtt/packet/MqttPacketPublish.java @@ -89,15 +89,14 @@ public class MqttPacketPublish extends MqttPacketHeader { // ------------------------------------------ // - Application data - @CustomBinaryField(index = 3000, serializer = MqttPacketPublishPayloadSerializer.class) - public byte[] payload; - - @Override public int calculatePayloadLength() { return payload == null ? 0 : payload.length; } + @CustomBinaryField(index = 3000, serializer = MqttPacketPublishPayloadSerializer.class) + public byte[] payload; + // ------------------------------------------ // Util methods // ------------------------------------------ diff --git a/src/zutil/net/mqtt/packet/MqttVariableIntSerializer.java b/src/zutil/net/mqtt/packet/MqttVariableIntSerializer.java index 10bd06f..0fb1b44 100755 --- a/src/zutil/net/mqtt/packet/MqttVariableIntSerializer.java +++ b/src/zutil/net/mqtt/packet/MqttVariableIntSerializer.java @@ -33,6 +33,7 @@ import java.io.OutputStream; /** * Code from MQTT specification + * @see 2.2.3 Remaining Length (variable length encoding scheme) */ public class MqttVariableIntSerializer implements BinaryFieldSerializer { @@ -60,7 +61,7 @@ public class MqttVariableIntSerializer implements BinaryFieldSerializer x = x / 128; // if there are more data to encode, set the top bit of this byte if (x > 0) - encodedByte = encodedByte & 128; + encodedByte = encodedByte | 128; out.write(encodedByte); } while (x > 0); } diff --git a/test/zutil/net/mqtt/packet/MqttPacketPublishTest.java b/test/zutil/net/mqtt/packet/MqttPacketPublishTest.java index bd02164..0de495e 100644 --- a/test/zutil/net/mqtt/packet/MqttPacketPublishTest.java +++ b/test/zutil/net/mqtt/packet/MqttPacketPublishTest.java @@ -8,6 +8,7 @@ import zutil.parser.binary.BinaryStructOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; import static org.junit.Assert.*; @@ -159,4 +160,59 @@ public class MqttPacketPublishTest { MqttPacket.write(binOut, obj); assertArrayEquals(Converter.toBytes(data), buffer.toByteArray()); } + + @Test + public void encodeQos2() throws IOException { + char[] data = new char[]{ + // Fixed Header + 0b0011_0100, // Packet Type(4) + Reserved(4) + 0xFF & 6, // Variable Header + Payload Length + // Variable Header + 0b0000_0000, // length + 0xFF & 2, // length + 'a', // Topic Name + 'b', // Topic Name + 0b0000_0000, // Packet ID + 0b0000_0101 // Packet ID + // Payload + }; + + MqttPacketPublish obj = new MqttPacketPublish(); + obj.setFlagQoS(MqttPacketPublish.PUBLISH_QOS_2); + obj.topicName = "ab"; + obj.packetId = 5; + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + BinaryStructOutputStream binOut = new BinaryStructOutputStream(buffer); + MqttPacket.write(binOut, obj); + assertArrayEquals(Converter.toBytes(data), buffer.toByteArray()); + } + + @Test + public void encodePayloadStream() throws IOException { + char[] data = new char[]{ + // Fixed Header + 0b0011_0000, // Packet Type(4) + Reserved(4) + 0xFF & 8, // Variable Header + Payload Length + // Variable Header + 0b0000_0000, // length + 0xFF & 2, // length + 'a', // Topic Name + 'b', // Topic Name + // Payload + 't', 'e', 's', 't', + + }; + + MqttPacketPublish obj = new MqttPacketPublish(); + obj.topicName = "ab"; + obj.payload = "test".getBytes(StandardCharsets.UTF_8); + + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + BinaryStructOutputStream binOut = new BinaryStructOutputStream(buffer); + + MqttPacket.write(binOut, obj); + + assertArrayEquals(Converter.toBytes(data), buffer.toByteArray()); + } } \ No newline at end of file diff --git a/test/zutil/net/mqtt/packet/MqttVariableIntSerializerTest.java b/test/zutil/net/mqtt/packet/MqttVariableIntSerializerTest.java new file mode 100644 index 0000000..fc075c4 --- /dev/null +++ b/test/zutil/net/mqtt/packet/MqttVariableIntSerializerTest.java @@ -0,0 +1,79 @@ +package zutil.net.mqtt.packet; + +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import static org.junit.Assert.*; + +public class MqttVariableIntSerializerTest { + + @Test + public void read() throws IOException { + MqttVariableIntSerializer serializer = new MqttVariableIntSerializer(); + + int actual = serializer.read(new ByteArrayInputStream(new byte[]{0x0}), null); + assertEquals(0, actual); + + actual = serializer.read(new ByteArrayInputStream(new byte[]{0x7f}), null); + assertEquals(127, actual); + + actual = serializer.read(new ByteArrayInputStream(new byte[]{(byte)0x80, 0x01}), null); + assertEquals(128, actual); + + actual = serializer.read(new ByteArrayInputStream(new byte[]{(byte)0xFF, 0x7f}), null); + assertEquals(16_383, actual); + + actual = serializer.read(new ByteArrayInputStream(new byte[]{(byte)0x80, (byte)0x80, 0x01}), null); + assertEquals(16_384, actual); + + actual = serializer.read(new ByteArrayInputStream(new byte[]{(byte)0xFF, (byte)0xFF, 0x7f}), null); + assertEquals(2_097_151, actual); + + actual = serializer.read(new ByteArrayInputStream(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x01}), null); + assertEquals(2_097_152, actual); + + actual = serializer.read(new ByteArrayInputStream(new byte[]{(byte)0xFF, (byte)0xFF, (byte)0xFF, 0x7f}), null); + assertEquals(268_435_455, actual); + } + + @Test + public void write() throws IOException { + MqttVariableIntSerializer serializer = new MqttVariableIntSerializer(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + out.reset(); + serializer.write(out, 0, null); + assertArrayEquals(new byte[]{0x0}, out.toByteArray()); + + out.reset(); + serializer.write(out, 127, null); + assertArrayEquals(new byte[]{0x7F}, out.toByteArray()); + + out.reset(); + serializer.write(out, 128, null); + assertArrayEquals(new byte[]{(byte)0x80, 0x01}, out.toByteArray()); + + out.reset(); + serializer.write(out, 16_383, null); + assertArrayEquals(new byte[]{(byte)0xFF, 0x7f}, out.toByteArray()); + + out.reset(); + serializer.write(out, 16_384, null); + assertArrayEquals(new byte[]{(byte)0x80, (byte)0x80, 0x01}, out.toByteArray()); + + out.reset(); + serializer.write(out, 2_097_151, null); + assertArrayEquals(new byte[]{(byte)0xFF, (byte)0xFF, 0x7f}, out.toByteArray()); + + out.reset(); + serializer.write(out, 2_097_152, null); + assertArrayEquals(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x01}, out.toByteArray()); + + out.reset(); + serializer.write(out, 268_435_455, null); + assertArrayEquals(new byte[]{(byte)0xFF, (byte)0xFF, (byte)0xFF, 0x7f}, out.toByteArray()); + } +} \ No newline at end of file