84 lines
2.8 KiB
JavaScript
84 lines
2.8 KiB
JavaScript
var Packet = require('./packets/packet');
|
|
|
|
// as this is very low level parser, EventEmitter is not used
|
|
// onPayload(sequenceId, payload) is called for each mysql packet
|
|
function PacketParser(onPacket)
|
|
{
|
|
// array of last payload chunks
|
|
// only used when corrent payload is not complete
|
|
this.buffer = [];
|
|
// total length of chunks on buffer
|
|
this.bufferLength = 0;
|
|
this.headerLen = 0;
|
|
this.headerBuff = Buffer(4);
|
|
|
|
this.state = 'head0';
|
|
|
|
// expected payload length
|
|
this.length = 0;
|
|
this.sequenceId = 0;
|
|
this.onPacket = onPacket;
|
|
}
|
|
|
|
PacketParser.prototype.execute = function(chunk, start, end) {
|
|
|
|
// node 0.11 has different ondata signature
|
|
if (!start && !end) {
|
|
start = 0;
|
|
end = chunk.length;
|
|
}
|
|
|
|
while (start < chunk.length) {
|
|
if (this.state == 'head0' && (end - start) > 3) {
|
|
this.length = chunk[start] + (chunk[start+1] << 8) + (chunk[start+2] << 16);
|
|
this.sequenceId = chunk[start+3];
|
|
var packetLength = this.length + 4;
|
|
if (end - start > packetLength) { // more than one packet in chunk
|
|
this.onPacket(new Packet(this.sequenceId, chunk, start + 4, start + packetLength));
|
|
start += packetLength;
|
|
} else if (end - start == packetLength) {
|
|
return this.onPacket(new Packet(this.sequenceId, chunk, start + 4, start + packetLength));
|
|
} else { // payload is incomplete
|
|
this.buffer = [chunk.slice(start + 4, end)];
|
|
this.bufferLength = end - start - 4;
|
|
this.state = 'payload';
|
|
return;
|
|
}
|
|
} else if (this.state == 'payload') {
|
|
var remainingPayload = this.length - this.bufferLength;
|
|
if (end - start >= remainingPayload) { // last chunk for payload
|
|
var payload = new Buffer(this.length);
|
|
var offset = 0;
|
|
for (var i=0; i < this.buffer.length; ++i) {
|
|
this.buffer[i].copy(payload, offset);
|
|
offset += this.buffer[i].length;
|
|
}
|
|
chunk.copy(payload, offset, start, start + remainingPayload);
|
|
this.onPacket(new Packet(this.sequenceId, payload, 0, this.length));
|
|
this.buffer = [];
|
|
this.bufferLength = 0;
|
|
start += remainingPayload;
|
|
this.state = 'head0';
|
|
} else {
|
|
this.buffer.push(chunk.slice(start, end));
|
|
this.bufferLength += end - start;
|
|
return;
|
|
}
|
|
} else { // length < 4 or state != header0
|
|
if (end - start + this.headerLen < 4) {
|
|
chunk.copy(this.headerBuff, this.headerLen, start, end);
|
|
this.headerLen += end - start;
|
|
this.state = 'head_';
|
|
return;
|
|
}
|
|
chunk.copy(this.headerBuff, this.headerLen, start, start + 4 - this.headerLen);
|
|
start += 4 - this.headerLen;
|
|
this.length = this.headerBuff[0] + (this.headerBuff[1] << 8) + (this.headerBuff[2] << 16);
|
|
this.headerLen = 0;
|
|
this.state = 'payload';
|
|
}
|
|
}
|
|
};
|
|
|
|
module.exports = PacketParser;
|