Backend half
This commit is contained in:
+142
@@ -0,0 +1,142 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
// Copyright (c) 2015-2024 MariaDB Corporation Ab
|
||||
|
||||
'use strict';
|
||||
|
||||
const ZLib = require('zlib');
|
||||
const Utils = require('../misc/utils');
|
||||
|
||||
/**
|
||||
* MySQL packet parser
|
||||
* see : https://mariadb.com/kb/en/library/0-packet/
|
||||
*/
|
||||
class CompressionInputStream {
|
||||
constructor(reader, receiveQueue, opts, info) {
|
||||
this.reader = reader;
|
||||
this.receiveQueue = receiveQueue;
|
||||
this.info = info;
|
||||
this.opts = opts;
|
||||
this.header = Buffer.allocUnsafe(7);
|
||||
this.headerLen = 0;
|
||||
this.compressPacketLen = null;
|
||||
this.packetLen = null;
|
||||
this.remainingLen = null;
|
||||
|
||||
this.parts = null;
|
||||
this.partsTotalLen = 0;
|
||||
}
|
||||
|
||||
receivePacket(chunk) {
|
||||
let cmd = this.currentCmd();
|
||||
if (this.opts.debugCompress) {
|
||||
this.opts.logger.network(
|
||||
`<== conn:${this.info.threadId ? this.info.threadId : -1} ${
|
||||
cmd
|
||||
? cmd.onPacketReceive
|
||||
? cmd.constructor.name + '.' + cmd.onPacketReceive.name
|
||||
: cmd.constructor.name
|
||||
: 'no command'
|
||||
} (compress)\n${Utils.log(this.opts, chunk, 0, chunk.length, this.header)}`
|
||||
);
|
||||
}
|
||||
if (cmd) cmd.compressSequenceNo = this.header[3];
|
||||
const unCompressLen = this.header[4] | (this.header[5] << 8) | (this.header[6] << 16);
|
||||
if (unCompressLen === 0) {
|
||||
this.reader.onData(chunk);
|
||||
} else {
|
||||
//use synchronous inflating, to ensure FIFO packet order
|
||||
const unCompressChunk = ZLib.inflateSync(chunk);
|
||||
this.reader.onData(unCompressChunk);
|
||||
}
|
||||
}
|
||||
|
||||
currentCmd() {
|
||||
let cmd;
|
||||
while ((cmd = this.receiveQueue.peek())) {
|
||||
if (cmd.onPacketReceive) return cmd;
|
||||
this.receiveQueue.shift();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
resetHeader() {
|
||||
this.remainingLen = null;
|
||||
this.headerLen = 0;
|
||||
}
|
||||
|
||||
onData(chunk) {
|
||||
let pos = 0;
|
||||
let length;
|
||||
const chunkLen = chunk.length;
|
||||
|
||||
do {
|
||||
if (this.remainingLen) {
|
||||
length = this.remainingLen;
|
||||
} else if (this.headerLen === 0 && chunkLen - pos >= 7) {
|
||||
this.header[0] = chunk[pos];
|
||||
this.header[1] = chunk[pos + 1];
|
||||
this.header[2] = chunk[pos + 2];
|
||||
this.header[3] = chunk[pos + 3];
|
||||
this.header[4] = chunk[pos + 4];
|
||||
this.header[5] = chunk[pos + 5];
|
||||
this.header[6] = chunk[pos + 6];
|
||||
this.headerLen = 7;
|
||||
pos += 7;
|
||||
this.compressPacketLen = this.header[0] + (this.header[1] << 8) + (this.header[2] << 16);
|
||||
this.packetLen = this.header[4] | (this.header[5] << 8) | (this.header[6] << 16);
|
||||
if (this.packetLen === 0) this.packetLen = this.compressPacketLen;
|
||||
length = this.compressPacketLen;
|
||||
} else {
|
||||
length = null;
|
||||
while (chunkLen - pos > 0) {
|
||||
this.header[this.headerLen++] = chunk[pos++];
|
||||
if (this.headerLen === 7) {
|
||||
this.compressPacketLen = this.header[0] + (this.header[1] << 8) + (this.header[2] << 16);
|
||||
this.packetLen = this.header[4] | (this.header[5] << 8) | (this.header[6] << 16);
|
||||
if (this.packetLen === 0) this.packetLen = this.compressPacketLen;
|
||||
length = this.compressPacketLen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (length) {
|
||||
if (chunkLen - pos >= length) {
|
||||
const buf = chunk.subarray(pos, pos + length);
|
||||
pos += length;
|
||||
if (this.parts) {
|
||||
this.parts.push(buf);
|
||||
this.partsTotalLen += length;
|
||||
|
||||
if (this.compressPacketLen < 0xffffff) {
|
||||
let buf = Buffer.concat(this.parts, this.partsTotalLen);
|
||||
this.parts = null;
|
||||
this.receivePacket(buf);
|
||||
}
|
||||
} else {
|
||||
if (this.compressPacketLen < 0xffffff) {
|
||||
this.receivePacket(buf);
|
||||
} else {
|
||||
this.parts = [buf];
|
||||
this.partsTotalLen = length;
|
||||
}
|
||||
}
|
||||
this.resetHeader();
|
||||
} else {
|
||||
const buf = chunk.subarray(pos, chunkLen);
|
||||
if (!this.parts) {
|
||||
this.parts = [buf];
|
||||
this.partsTotalLen = chunkLen - pos;
|
||||
} else {
|
||||
this.parts.push(buf);
|
||||
this.partsTotalLen += chunkLen - pos;
|
||||
}
|
||||
this.remainingLen = length - (chunkLen - pos);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} while (pos < chunkLen);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CompressionInputStream;
|
||||
Reference in New Issue
Block a user