mudb
Version:
Real-time database for multiplayer games
95 lines (78 loc) • 2.35 kB
text/typescript
import { MuData } from '../socket';
enum Read {
HEADER,
PAYLOAD,
}
const HEADER_LENGTH = 4;
// TODO minimize buffer allocation
export function messagify (socket) {
let bufSize = 0;
const buf:Buffer[] = [];
let hasMsg = false;
let next = Read.HEADER;
let msgLength = 0;
function readBuf (length:number) : Buffer {
bufSize -= length;
if (length === buf[0].length) {
return buf.shift() as Buffer;
}
let result:Buffer;
if (length < buf[0].length) {
result = buf[0].slice(0, length);
buf[0] = buf[0].slice(length);
return result;
}
result = Buffer.allocUnsafe(length);
let offset = 0;
let bl;
while (length > 0) {
bl = buf[0].length;
if (length >= bl) {
buf[0].copy(result, offset);
offset += bl;
buf.shift();
} else {
buf[0].copy(result, offset, 0, length);
buf[0] = buf[0].slice(length);
}
length -= bl;
}
return result;
}
function fetchMsg () {
while (hasMsg) {
if (next === Read.HEADER) {
if (bufSize >= HEADER_LENGTH) {
next = Read.PAYLOAD;
msgLength = readBuf(HEADER_LENGTH).readUInt32LE(0);
} else {
hasMsg = false;
}
} else if (next === Read.PAYLOAD) {
if (bufSize >= msgLength) {
next = Read.HEADER;
socket.emit('message', readBuf(msgLength));
} else {
hasMsg = false;
}
}
}
}
const socketWrite = socket.write.bind(socket);
socket.write = function (data:MuData) {
const payload = Buffer.from(data);
const header = Buffer.allocUnsafe(HEADER_LENGTH);
header.writeUInt32LE(payload.length, 0);
socketWrite(header);
socketWrite(payload);
};
socket.on('data', (data) => {
buf.push(data);
bufSize += data.length;
hasMsg = true;
fetchMsg();
});
}
export function isJSON (buf:Buffer) {
return buf[0] === 0x7b && buf[buf.length - 1] === 0x7d;
}