Serialize text size on 4 bytes
This will allow to send text having a size greater than 65535 bytes.
This commit is contained in:
parent
d91c5dcfd5
commit
245999aec4
10 changed files with 40 additions and 36 deletions
|
@ -20,9 +20,9 @@ write_position(uint8_t *buf, const struct position *position) {
|
||||||
static size_t
|
static size_t
|
||||||
write_string(const char *utf8, size_t max_len, unsigned char *buf) {
|
write_string(const char *utf8, size_t max_len, unsigned char *buf) {
|
||||||
size_t len = utf8_truncation_index(utf8, max_len);
|
size_t len = utf8_truncation_index(utf8, max_len);
|
||||||
buffer_write16be(buf, (uint16_t) len);
|
buffer_write32be(buf, len);
|
||||||
memcpy(&buf[2], utf8, len);
|
memcpy(&buf[4], utf8, len);
|
||||||
return 2 + len;
|
return 4 + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t
|
static uint16_t
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
#define CONTROL_MSG_MAX_SIZE 4096
|
#define CONTROL_MSG_MAX_SIZE 4096
|
||||||
|
|
||||||
#define CONTROL_MSG_INJECT_TEXT_MAX_LENGTH 300
|
#define CONTROL_MSG_INJECT_TEXT_MAX_LENGTH 300
|
||||||
// type: 1 byte; paste flag: 1 byte; length: 2 bytes
|
// type: 1 byte; paste flag: 1 byte; length: 4 bytes
|
||||||
#define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH (CONTROL_MSG_MAX_SIZE - 4)
|
#define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH (CONTROL_MSG_MAX_SIZE - 6)
|
||||||
|
|
||||||
#define POINTER_ID_MOUSE UINT64_C(-1);
|
#define POINTER_ID_MOUSE UINT64_C(-1);
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
ssize_t
|
ssize_t
|
||||||
device_msg_deserialize(const unsigned char *buf, size_t len,
|
device_msg_deserialize(const unsigned char *buf, size_t len,
|
||||||
struct device_msg *msg) {
|
struct device_msg *msg) {
|
||||||
if (len < 3) {
|
if (len < 5) {
|
||||||
// at least type + empty string length
|
// at least type + empty string length
|
||||||
return 0; // not available
|
return 0; // not available
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@ device_msg_deserialize(const unsigned char *buf, size_t len,
|
||||||
msg->type = buf[0];
|
msg->type = buf[0];
|
||||||
switch (msg->type) {
|
switch (msg->type) {
|
||||||
case DEVICE_MSG_TYPE_CLIPBOARD: {
|
case DEVICE_MSG_TYPE_CLIPBOARD: {
|
||||||
uint16_t clipboard_len = buffer_read16be(&buf[1]);
|
size_t clipboard_len = buffer_read32be(&buf[1]);
|
||||||
if (clipboard_len > len - 3) {
|
if (clipboard_len > len - 5) {
|
||||||
return 0; // not available
|
return 0; // not available
|
||||||
}
|
}
|
||||||
char *text = SDL_malloc(clipboard_len + 1);
|
char *text = SDL_malloc(clipboard_len + 1);
|
||||||
|
@ -27,12 +27,12 @@ device_msg_deserialize(const unsigned char *buf, size_t len,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (clipboard_len) {
|
if (clipboard_len) {
|
||||||
memcpy(text, &buf[3], clipboard_len);
|
memcpy(text, &buf[5], clipboard_len);
|
||||||
}
|
}
|
||||||
text[clipboard_len] = '\0';
|
text[clipboard_len] = '\0';
|
||||||
|
|
||||||
msg->clipboard.text = text;
|
msg->clipboard.text = text;
|
||||||
return 3 + clipboard_len;
|
return 5 + clipboard_len;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
LOGW("Unknown device message type: %d", (int) msg->type);
|
LOGW("Unknown device message type: %d", (int) msg->type);
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#define DEVICE_MSG_MAX_SIZE 4096
|
#define DEVICE_MSG_MAX_SIZE 4096
|
||||||
// type: 1 byte; length: 2 bytes
|
// type: 1 byte; length: 4 bytes
|
||||||
#define DEVICE_MSG_TEXT_MAX_LENGTH (DEVICE_MSG_MAX_SIZE - 3)
|
#define DEVICE_MSG_TEXT_MAX_LENGTH (DEVICE_MSG_MAX_SIZE - 5)
|
||||||
|
|
||||||
enum device_msg_type {
|
enum device_msg_type {
|
||||||
DEVICE_MSG_TYPE_CLIPBOARD,
|
DEVICE_MSG_TYPE_CLIPBOARD,
|
||||||
|
|
|
@ -36,11 +36,11 @@ static void test_serialize_inject_text(void) {
|
||||||
|
|
||||||
unsigned char buf[CONTROL_MSG_MAX_SIZE];
|
unsigned char buf[CONTROL_MSG_MAX_SIZE];
|
||||||
int size = control_msg_serialize(&msg, buf);
|
int size = control_msg_serialize(&msg, buf);
|
||||||
assert(size == 16);
|
assert(size == 18);
|
||||||
|
|
||||||
const unsigned char expected[] = {
|
const unsigned char expected[] = {
|
||||||
CONTROL_MSG_TYPE_INJECT_TEXT,
|
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
|
'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', // text
|
||||||
};
|
};
|
||||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
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];
|
unsigned char buf[CONTROL_MSG_MAX_SIZE];
|
||||||
int size = control_msg_serialize(&msg, buf);
|
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[0] = CONTROL_MSG_TYPE_INJECT_TEXT;
|
||||||
expected[1] = 0x01;
|
expected[1] = 0x00;
|
||||||
expected[2] = 0x2c; // text length (16 bits)
|
expected[2] = 0x00;
|
||||||
memset(&expected[3], 'a', CONTROL_MSG_INJECT_TEXT_MAX_LENGTH);
|
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)));
|
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||||
}
|
}
|
||||||
|
@ -208,12 +210,12 @@ static void test_serialize_set_clipboard(void) {
|
||||||
|
|
||||||
unsigned char buf[CONTROL_MSG_MAX_SIZE];
|
unsigned char buf[CONTROL_MSG_MAX_SIZE];
|
||||||
int size = control_msg_serialize(&msg, buf);
|
int size = control_msg_serialize(&msg, buf);
|
||||||
assert(size == 17);
|
assert(size == 19);
|
||||||
|
|
||||||
const unsigned char expected[] = {
|
const unsigned char expected[] = {
|
||||||
CONTROL_MSG_TYPE_SET_CLIPBOARD,
|
CONTROL_MSG_TYPE_SET_CLIPBOARD,
|
||||||
1, // paste
|
1, // paste
|
||||||
0x00, 0x0d, // text length
|
0x00, 0x00, 0x00, 0x0d, // text length
|
||||||
'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', // text
|
'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', // text
|
||||||
};
|
};
|
||||||
assert(!memcmp(buf, expected, sizeof(expected)));
|
assert(!memcmp(buf, expected, sizeof(expected)));
|
||||||
|
|
|
@ -8,13 +8,13 @@
|
||||||
static void test_deserialize_clipboard(void) {
|
static void test_deserialize_clipboard(void) {
|
||||||
const unsigned char input[] = {
|
const unsigned char input[] = {
|
||||||
DEVICE_MSG_TYPE_CLIPBOARD,
|
DEVICE_MSG_TYPE_CLIPBOARD,
|
||||||
0x00, 0x03, // text length
|
0x00, 0x00, 0x00, 0x03, // text length
|
||||||
0x41, 0x42, 0x43, // "ABC"
|
0x41, 0x42, 0x43, // "ABC"
|
||||||
};
|
};
|
||||||
|
|
||||||
struct device_msg msg;
|
struct device_msg msg;
|
||||||
ssize_t r = device_msg_deserialize(input, sizeof(input), &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.type == DEVICE_MSG_TYPE_CLIPBOARD);
|
||||||
assert(msg.clipboard.text);
|
assert(msg.clipboard.text);
|
||||||
|
@ -26,10 +26,12 @@ static void test_deserialize_clipboard(void) {
|
||||||
static void test_deserialize_clipboard_big(void) {
|
static void test_deserialize_clipboard_big(void) {
|
||||||
unsigned char input[DEVICE_MSG_MAX_SIZE];
|
unsigned char input[DEVICE_MSG_MAX_SIZE];
|
||||||
input[0] = DEVICE_MSG_TYPE_CLIPBOARD;
|
input[0] = DEVICE_MSG_TYPE_CLIPBOARD;
|
||||||
input[1] = DEVICE_MSG_TEXT_MAX_LENGTH >> 8; // MSB
|
input[1] = (DEVICE_MSG_TEXT_MAX_LENGTH & 0xff000000u) >> 24;
|
||||||
input[2] = DEVICE_MSG_TEXT_MAX_LENGTH & 0xff; // LSB
|
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;
|
struct device_msg msg;
|
||||||
ssize_t r = device_msg_deserialize(input, sizeof(input), &msg);
|
ssize_t r = device_msg_deserialize(input, sizeof(input), &msg);
|
||||||
|
|
|
@ -16,7 +16,7 @@ public class ControlMessageReader {
|
||||||
|
|
||||||
private static final int MESSAGE_MAX_SIZE = 4096;
|
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;
|
public static final int INJECT_TEXT_MAX_LENGTH = 300;
|
||||||
|
|
||||||
private final byte[] rawBuffer = new byte[MESSAGE_MAX_SIZE];
|
private final byte[] rawBuffer = new byte[MESSAGE_MAX_SIZE];
|
||||||
|
@ -103,10 +103,10 @@ public class ControlMessageReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String parseString() {
|
private String parseString() {
|
||||||
if (buffer.remaining() < 2) {
|
if (buffer.remaining() < 4) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
int len = toUnsigned(buffer.getShort());
|
int len = buffer.getInt();
|
||||||
if (buffer.remaining() < len) {
|
if (buffer.remaining() < len) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import java.nio.charset.StandardCharsets;
|
||||||
public class DeviceMessageWriter {
|
public class DeviceMessageWriter {
|
||||||
|
|
||||||
private static final int MESSAGE_MAX_SIZE = 4096;
|
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 byte[] rawBuffer = new byte[MESSAGE_MAX_SIZE];
|
||||||
private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer);
|
private final ByteBuffer buffer = ByteBuffer.wrap(rawBuffer);
|
||||||
|
@ -21,7 +21,7 @@ public class DeviceMessageWriter {
|
||||||
String text = msg.getText();
|
String text = msg.getText();
|
||||||
byte[] raw = text.getBytes(StandardCharsets.UTF_8);
|
byte[] raw = text.getBytes(StandardCharsets.UTF_8);
|
||||||
int len = StringUtils.getUtf8TruncationIndex(raw, CLIPBOARD_TEXT_MAX_LENGTH);
|
int len = StringUtils.getUtf8TruncationIndex(raw, CLIPBOARD_TEXT_MAX_LENGTH);
|
||||||
buffer.putShort((short) len);
|
buffer.putInt(len);
|
||||||
buffer.put(raw, 0, len);
|
buffer.put(raw, 0, len);
|
||||||
output.write(rawBuffer, 0, buffer.position());
|
output.write(rawBuffer, 0, buffer.position());
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -48,7 +48,7 @@ public class ControlMessageReaderTest {
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
dos.writeByte(ControlMessage.TYPE_INJECT_TEXT);
|
dos.writeByte(ControlMessage.TYPE_INJECT_TEXT);
|
||||||
byte[] text = "testé".getBytes(StandardCharsets.UTF_8);
|
byte[] text = "testé".getBytes(StandardCharsets.UTF_8);
|
||||||
dos.writeShort(text.length);
|
dos.writeInt(text.length);
|
||||||
dos.write(text);
|
dos.write(text);
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ public class ControlMessageReaderTest {
|
||||||
dos.writeByte(ControlMessage.TYPE_INJECT_TEXT);
|
dos.writeByte(ControlMessage.TYPE_INJECT_TEXT);
|
||||||
byte[] text = new byte[ControlMessageReader.INJECT_TEXT_MAX_LENGTH];
|
byte[] text = new byte[ControlMessageReader.INJECT_TEXT_MAX_LENGTH];
|
||||||
Arrays.fill(text, (byte) 'a');
|
Arrays.fill(text, (byte) 'a');
|
||||||
dos.writeShort(text.length);
|
dos.writeInt(text.length);
|
||||||
dos.write(text);
|
dos.write(text);
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ public class ControlMessageReaderTest {
|
||||||
dos.writeByte(ControlMessage.TYPE_SET_CLIPBOARD);
|
dos.writeByte(ControlMessage.TYPE_SET_CLIPBOARD);
|
||||||
dos.writeByte(1); // paste
|
dos.writeByte(1); // paste
|
||||||
byte[] text = "testé".getBytes(StandardCharsets.UTF_8);
|
byte[] text = "testé".getBytes(StandardCharsets.UTF_8);
|
||||||
dos.writeShort(text.length);
|
dos.writeInt(text.length);
|
||||||
dos.write(text);
|
dos.write(text);
|
||||||
|
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
|
@ -246,7 +246,7 @@ public class ControlMessageReaderTest {
|
||||||
Arrays.fill(rawText, (byte) 'a');
|
Arrays.fill(rawText, (byte) 'a');
|
||||||
String text = new String(rawText, 0, rawText.length);
|
String text = new String(rawText, 0, rawText.length);
|
||||||
|
|
||||||
dos.writeShort(rawText.length);
|
dos.writeInt(rawText.length);
|
||||||
dos.write(rawText);
|
dos.write(rawText);
|
||||||
|
|
||||||
byte[] packet = bos.toByteArray();
|
byte[] packet = bos.toByteArray();
|
||||||
|
|
|
@ -19,7 +19,7 @@ public class DeviceMessageWriterTest {
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
DataOutputStream dos = new DataOutputStream(bos);
|
DataOutputStream dos = new DataOutputStream(bos);
|
||||||
dos.writeByte(DeviceMessage.TYPE_CLIPBOARD);
|
dos.writeByte(DeviceMessage.TYPE_CLIPBOARD);
|
||||||
dos.writeShort(data.length);
|
dos.writeInt(data.length);
|
||||||
dos.write(data);
|
dos.write(data);
|
||||||
|
|
||||||
byte[] expected = bos.toByteArray();
|
byte[] expected = bos.toByteArray();
|
||||||
|
|
Loading…
Reference in a new issue