Fix packing large buffers

parent ec950103
Pipeline #286 failed with stages
in 5 minutes and 22 seconds
......@@ -54,6 +54,7 @@ export class CFLBinaryPListComposer {
buffer['write' + sizes[size]](object, 0, size);
string = buffer.toString('binary');
break;
} catch (err) {
size = null;
}
......@@ -68,7 +69,6 @@ export class CFLBinaryPListComposer {
data += String.fromCharCode(marker);
data += string;
} else if (typeof object === 'number') {
let string = '', size = null;
const sizes = {1: '8', 2: '16BE', 4: '32BE'};
......@@ -96,13 +96,13 @@ export class CFLBinaryPListComposer {
data += string;
} else if (typeof object === 'object' && object instanceof Buffer) {
if (object.length >= 0xf) {
data += String.fromCharCode(0xf);
data += String.fromCharCode(0x4f);
data += this.packObject(object.length, depth + 1);
} else {
data += String.fromCharCode(0x40 + object.length);
}
data += object;
data += object.toString('binary');
} else if (typeof object === 'string') {
data += '\x70';
data += Buffer.from(object, 'utf8').toString('binary');
......
......@@ -103,13 +103,13 @@ export default class Message {
return buffer.toString('binary');
}
static async parseRaw(data) {
static async parseRaw(data, return_remaining) {
if (HEADER_SIZE > data.length) {
throw new Error(`Need to pass at least ${HEADER_SIZE} bytes`);
}
const header_data = data.substr(0, HEADER_SIZE);
const body_data = data.length > HEADER_SIZE ? data.substr(HEADER_SIZE) : undefined;
let body_data = data.length > HEADER_SIZE ? data.substr(HEADER_SIZE) : undefined;
const {magic, version, header_checksum, body_checksum, body_size, flags, unused, command, error_code, key, pad1, pad2} = this.unpackHeader(header_data);
......@@ -134,6 +134,10 @@ export default class Message {
throw new Error('Header checksum does not match');
}
if (body_data && return_remaining) {
body_data = body_data.substr(0, body_size);
}
if (body_data && body_size === -1) {
throw new Error('Cannot handle stream header with data attached');
}
......@@ -156,7 +160,11 @@ export default class Message {
// TODO: check error code
return new Message(version, flags, unused, command, error_code, key, body_data, body_size);
const message = new Message(version, flags, unused, command, error_code, key, body_data, body_size);
if (return_remaining) return [message, data.substr(HEADER_SIZE + body_size)];
return message;
}
static composeEchoCommand(flags, password, payload) {
......
......@@ -63,15 +63,21 @@ export default class Server {
session.buffer += data.toString('binary');
// Try decoding the data as a message
if (session.buffer.length >= MESSAGE_HEADER_SIZE) {
this.tryHandleMessage(session);
}
this.handleData(session);
});
}
async tryHandleMessage(session, buffer) {
async handleData(session) {
while (session.buffer.length >= MESSAGE_HEADER_SIZE) {
await this.tryHandleMessage(session);
}
}
async tryHandleMessage(session) {
try {
const message = await Message.parseRaw(session.buffer);
const [message, data] = await Message.parseRaw(session.buffer, true);
session.buffer = data;
if (message.body.length !== message.body_size) {
// Haven't received the message body yet
......@@ -82,7 +88,7 @@ export default class Server {
this.handleMessage(session, message);
} catch (err) {
console.error(session, err);
console.error('Error handling message from', session.host, session.port, err);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment