From 245999aec4a4a1454212b38a988aa96fa701bb04 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Thu, 4 Jun 2020 21:42:09 +0200 Subject: [PATCH] Serialize text size on 4 bytes This will allow to send text having a size greater than 65535 bytes. --- app/src/control_msg.c | 6 +++--- app/src/control_msg.h | 4 ++-- app/src/device_msg.c | 10 +++++----- app/src/device_msg.h | 4 ++-- app/tests/test_control_msg_serialize.c | 20 ++++++++++--------- app/tests/test_device_msg_deserialize.c | 12 ++++++----- .../scrcpy/ControlMessageReader.java | 6 +++--- .../scrcpy/DeviceMessageWriter.java | 4 ++-- .../scrcpy/ControlMessageReaderTest.java | 8 ++++---- .../scrcpy/DeviceMessageWriterTest.java | 2 +- 10 files changed, 40 insertions(+), 36 deletions(-) diff --git a/app/src/control_msg.c b/app/src/control_msg.c index c5778c02..2a7f2f34 100644 --- a/app/src/control_msg.c +++ b/app/src/control_msg.c @@ -20,9 +20,9 @@ write_position(uint8_t *buf, const struct position *position) { static size_t write_string(const char *utf8, size_t max_len, unsigned char *buf) { size_t len = utf8_truncation_index(utf8, max_len); - buffer_write16be(buf, (uint16_t) len); - memcpy(&buf[2], utf8, len); - return 2 + len; + buffer_write32be(buf, len); + memcpy(&buf[4], utf8, len); + return 4 + len; } static uint16_t diff --git a/app/src/control_msg.h b/app/src/control_msg.h index f5d633a8..d8898c9c 100644 --- a/app/src/control_msg.h +++ b/app/src/control_msg.h @@ -13,8 +13,8 @@ #define CONTROL_MSG_MAX_SIZE 4096 #define CONTROL_MSG_INJECT_TEXT_MAX_LENGTH 300 -// type: 1 byte; paste flag: 1 byte; length: 2 bytes -#define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH (CONTROL_MSG_MAX_SIZE - 4) +// type: 1 byte; paste flag: 1 byte; length: 4 bytes +#define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH (CONTROL_MSG_MAX_SIZE - 6) #define POINTER_ID_MOUSE UINT64_C(-1); diff --git a/app/src/device_msg.c b/app/src/device_msg.c index db176129..09e68936 100644 --- a/app/src/device_msg.c +++ b/app/src/device_msg.c @@ -9,7 +9,7 @@ ssize_t device_msg_deserialize(const unsigned char *buf, size_t len, struct device_msg *msg) { - if (len < 3) { + if (len < 5) { // at least type + empty string length return 0; // not available } @@ -17,8 +17,8 @@ device_msg_deserialize(const unsigned char *buf, size_t len, msg->type = buf[0]; switch (msg->type) { case DEVICE_MSG_TYPE_CLIPBOARD: { - uint16_t clipboard_len = buffer_read16be(&buf[1]); - if (clipboard_len > len - 3) { + size_t clipboard_len = buffer_read32be(&buf[1]); + if (clipboard_len > len - 5) { return 0; // not available } char *text = SDL_malloc(clipboard_len + 1); @@ -27,12 +27,12 @@ device_msg_deserialize(const unsigned char *buf, size_t len, return -1; } if (clipboard_len) { - memcpy(text, &buf[3], clipboard_len); + memcpy(text, &buf[5], clipboard_len); } text[clipboard_len] = '\0'; msg->clipboard.text = text; - return 3 + clipboard_len; + return 5 + clipboard_len; } default: LOGW("Unknown device message type: %d", (int) msg->type); diff --git a/app/src/device_msg.h b/app/src/device_msg.h index 60c35817..0fc7d87c 100644 --- a/app/src/device_msg.h +++ b/app/src/device_msg.h @@ -8,8 +8,8 @@ #include "config.h" #define DEVICE_MSG_MAX_SIZE 4096 -// type: 1 byte; length: 2 bytes -#define DEVICE_MSG_TEXT_MAX_LENGTH (DEVICE_MSG_MAX_SIZE - 3) +// type: 1 byte; length: 4 bytes +#define DEVICE_MSG_TEXT_MAX_LENGTH (DEVICE_MSG_MAX_SIZE - 5) enum device_msg_type { DEVICE_MSG_TYPE_CLIPBOARD, diff --git a/app/tests/test_control_msg_serialize.c b/app/tests/test_control_msg_serialize.c index a0328060..9ba90ae8 100644 --- a/app/tests/test_control_msg_serialize.c +++ b/app/tests/test_control_msg_serialize.c @@ -36,11 +36,11 @@ static void test_serialize_inject_text(void) { unsigned char buf[CONTROL_MSG_MAX_SIZE]; int size = control_msg_serialize(&msg, buf); - assert(size == 16); + assert(size == 18); const unsigned char expected[] = { CONTROL_MSG_TYPE_INJECT_TEXT, - 0x00, 0x0d, // text length + 0x00, 0x00, 0x00, 0x0d, // text length 'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', // text }; assert(!memcmp(buf, expected, sizeof(expected))); @@ -56,13 +56,15 @@ static void test_serialize_inject_text_long(void) { unsigned char buf[CONTROL_MSG_MAX_SIZE]; int size = control_msg_serialize(&msg, buf); - assert(size == 3 + CONTROL_MSG_INJECT_TEXT_MAX_LENGTH); + assert(size == 5 + CONTROL_MSG_INJECT_TEXT_MAX_LENGTH); - unsigned char expected[3 + CONTROL_MSG_INJECT_TEXT_MAX_LENGTH]; + unsigned char expected[5 + CONTROL_MSG_INJECT_TEXT_MAX_LENGTH]; expected[0] = CONTROL_MSG_TYPE_INJECT_TEXT; - expected[1] = 0x01; - expected[2] = 0x2c; // text length (16 bits) - memset(&expected[3], 'a', CONTROL_MSG_INJECT_TEXT_MAX_LENGTH); + expected[1] = 0x00; + expected[2] = 0x00; + expected[3] = 0x01; + expected[4] = 0x2c; // text length (32 bits) + memset(&expected[5], 'a', CONTROL_MSG_INJECT_TEXT_MAX_LENGTH); assert(!memcmp(buf, expected, sizeof(expected))); } @@ -208,12 +210,12 @@ static void test_serialize_set_clipboard(void) { unsigned char buf[CONTROL_MSG_MAX_SIZE]; int size = control_msg_serialize(&msg, buf); - assert(size == 17); + assert(size == 19); const unsigned char expected[] = { CONTROL_MSG_TYPE_SET_CLIPBOARD, 1, // paste - 0x00, 0x0d, // text length + 0x00, 0x00, 0x00, 0x0d, // text length 'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', // text }; assert(!memcmp(buf, expected, sizeof(expected))); diff --git a/app/tests/test_device_msg_deserialize.c b/app/tests/test_device_msg_deserialize.c index 6a38d5e5..8fcfc93d 100644 --- a/app/tests/test_device_msg_deserialize.c +++ b/app/tests/test_device_msg_deserialize.c @@ -8,13 +8,13 @@ static void test_deserialize_clipboard(void) { const unsigned char input[] = { DEVICE_MSG_TYPE_CLIPBOARD, - 0x00, 0x03, // text length + 0x00, 0x00, 0x00, 0x03, // text length 0x41, 0x42, 0x43, // "ABC" }; struct device_msg msg; ssize_t r = device_msg_deserialize(input, sizeof(input), &msg); - assert(r == 6); + assert(r == 8); assert(msg.type == DEVICE_MSG_TYPE_CLIPBOARD); assert(msg.clipboard.text); @@ -26,10 +26,12 @@ static void test_deserialize_clipboard(void) { static void test_deserialize_clipboard_big(void) { unsigned char input[DEVICE_MSG_MAX_SIZE]; input[0] = DEVICE_MSG_TYPE_CLIPBOARD; - input[1] = DEVICE_MSG_TEXT_MAX_LENGTH >> 8; // MSB - input[2] = DEVICE_MSG_TEXT_MAX_LENGTH & 0xff; // LSB + input[1] = (DEVICE_MSG_TEXT_MAX_LENGTH & 0xff000000u) >> 24; + input[2] = (DEVICE_MSG_TEXT_MAX_LENGTH & 0x00ff0000u) >> 16; + input[3] = (DEVICE_MSG_TEXT_MAX_LENGTH & 0x0000ff00u) >> 8; + input[4] = DEVICE_MSG_TEXT_MAX_LENGTH & 0x000000ffu; - memset(input + 3, 'a', DEVICE_MSG_TEXT_MAX_LENGTH); + memset(input + 5, 'a', DEVICE_MSG_TEXT_MAX_LENGTH); struct device_msg msg; ssize_t r = device_msg_deserialize(input, sizeof(input), &msg); diff --git a/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java b/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java index b8fba824..a9905919 100644 --- a/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java +++ b/server/src/main/java/com/genymobile/scrcpy/ControlMessageReader.java @@ -16,7 +16,7 @@ public class ControlMessageReader { private static final int MESSAGE_MAX_SIZE = 4096; - public static final int CLIPBOARD_TEXT_MAX_LENGTH = MESSAGE_MAX_SIZE - 4; // type: 1 byte; paste flag: 1 byte; length: 2 bytes + public static final int CLIPBOARD_TEXT_MAX_LENGTH = MESSAGE_MAX_SIZE - 6; // type: 1 byte; paste flag: 1 byte; length: 4 bytes public static final int INJECT_TEXT_MAX_LENGTH = 300; private final byte[] rawBuffer = new byte[MESSAGE_MAX_SIZE]; @@ -103,10 +103,10 @@ public class ControlMessageReader { } private String parseString() { - if (buffer.remaining() < 2) { + if (buffer.remaining() < 4) { return null; } - int len = toUnsigned(buffer.getShort()); + int len = buffer.getInt(); if (buffer.remaining() < len) { return null; } diff --git a/server/src/main/java/com/genymobile/scrcpy/DeviceMessageWriter.java b/server/src/main/java/com/genymobile/scrcpy/DeviceMessageWriter.java index ea54d533..2e12698f 100644 --- a/server/src/main/java/com/genymobile/scrcpy/DeviceMessageWriter.java +++ b/server/src/main/java/com/genymobile/scrcpy/DeviceMessageWriter.java @@ -8,7 +8,7 @@ import java.nio.charset.StandardCharsets; public class DeviceMessageWriter { private static final int MESSAGE_MAX_SIZE = 4096; - public static final int CLIPBOARD_TEXT_MAX_LENGTH = MESSAGE_MAX_SIZE - 3; // type: 1 byte; length: 2 bytes + public static final int CLIPBOARD_TEXT_MAX_LENGTH = MESSAGE_MAX_SIZE - 5; // type: 1 byte; length: 4 bytes private final byte[] rawBuffer = new byte[MESSAGE_MAX_SIZE]; private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer); @@ -21,7 +21,7 @@ public class DeviceMessageWriter { String text = msg.getText(); byte[] raw = text.getBytes(StandardCharsets.UTF_8); int len = StringUtils.getUtf8TruncationIndex(raw, CLIPBOARD_TEXT_MAX_LENGTH); - buffer.putShort((short) len); + buffer.putInt(len); buffer.put(raw, 0, len); output.write(rawBuffer, 0, buffer.position()); break; diff --git a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java index f5fa4d09..c56bd17e 100644 --- a/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java +++ b/server/src/test/java/com/genymobile/scrcpy/ControlMessageReaderTest.java @@ -48,7 +48,7 @@ public class ControlMessageReaderTest { DataOutputStream dos = new DataOutputStream(bos); dos.writeByte(ControlMessage.TYPE_INJECT_TEXT); byte[] text = "testé".getBytes(StandardCharsets.UTF_8); - dos.writeShort(text.length); + dos.writeInt(text.length); dos.write(text); byte[] packet = bos.toByteArray(); @@ -68,7 +68,7 @@ public class ControlMessageReaderTest { dos.writeByte(ControlMessage.TYPE_INJECT_TEXT); byte[] text = new byte[ControlMessageReader.INJECT_TEXT_MAX_LENGTH]; Arrays.fill(text, (byte) 'a'); - dos.writeShort(text.length); + dos.writeInt(text.length); dos.write(text); byte[] packet = bos.toByteArray(); @@ -218,7 +218,7 @@ public class ControlMessageReaderTest { dos.writeByte(ControlMessage.TYPE_SET_CLIPBOARD); dos.writeByte(1); // paste byte[] text = "testé".getBytes(StandardCharsets.UTF_8); - dos.writeShort(text.length); + dos.writeInt(text.length); dos.write(text); byte[] packet = bos.toByteArray(); @@ -246,7 +246,7 @@ public class ControlMessageReaderTest { Arrays.fill(rawText, (byte) 'a'); String text = new String(rawText, 0, rawText.length); - dos.writeShort(rawText.length); + dos.writeInt(rawText.length); dos.write(rawText); byte[] packet = bos.toByteArray(); diff --git a/server/src/test/java/com/genymobile/scrcpy/DeviceMessageWriterTest.java b/server/src/test/java/com/genymobile/scrcpy/DeviceMessageWriterTest.java index df12f647..88bf2af9 100644 --- a/server/src/test/java/com/genymobile/scrcpy/DeviceMessageWriterTest.java +++ b/server/src/test/java/com/genymobile/scrcpy/DeviceMessageWriterTest.java @@ -19,7 +19,7 @@ public class DeviceMessageWriterTest { ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); dos.writeByte(DeviceMessage.TYPE_CLIPBOARD); - dos.writeShort(data.length); + dos.writeInt(data.length); dos.write(data); byte[] expected = bos.toByteArray();