Skip to content

Commit 98f1485

Browse files
authored
Merge eb7f3a2 into 283425b
2 parents 283425b + eb7f3a2 commit 98f1485

File tree

7 files changed

+98
-21
lines changed

7 files changed

+98
-21
lines changed

Changes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ you spot any mistakes.
3131
* Fix `connection.threadId` missing on handshake failure
3232
* Fix duplicate packet name in debug output
3333
* Fix no password support for old password protocol
34+
* Fix suppression of fatal protocol server errors #2021
3435
* Remove special case for handshake in determine packet code
3536
* Small performance improvement starting command sequence
3637
* Support auth switch in change user flow #1776

lib/Connection.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ function Connection(options) {
1515

1616
this.config = options.config;
1717

18+
this._buffer = [];
1819
this._socket = options.socket;
1920
this._protocol = new Protocol({config: this.config, connection: this});
2021
this._connectCalled = false;
@@ -81,8 +82,18 @@ Connection.prototype.connect = function connect(options, callback) {
8182
}
8283

8384
var connection = this;
84-
this._protocol.on('data', function(data) {
85-
connection._socket.write(data);
85+
var onWrite = function onWrite() {
86+
if (connection._buffer.shift() && connection._buffer.length > 0) {
87+
setTimeout(function () {
88+
connection._socket.write(connection._buffer[0], onWrite);
89+
}, 10);
90+
}
91+
};
92+
93+
this._protocol.on('data', function (data) {
94+
if (connection._buffer.push(data) === 1) {
95+
connection._socket.write(data, onWrite);
96+
}
8697
});
8798
this._socket.on('data', wrapToDomain(connection, function (data) {
8899
connection._protocol.write(data);

lib/protocol/PacketWriter.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ var BUFFER_ALLOC_SIZE = Math.pow(2, 8);
55
// Don't panic: Good enough to represent byte values up to 8192 TB
66
var IEEE_754_BINARY_64_PRECISION = Math.pow(2, 53);
77
var MAX_PACKET_LENGTH = Math.pow(2, 24) - 1;
8-
var Buffer = require('safe-buffer').Buffer;
8+
9+
var Buffer = require('safe-buffer').Buffer;
10+
var EventEmitter = require('events').EventEmitter;
11+
var Util = require('util');
912

1013
module.exports = PacketWriter;
1114
function PacketWriter() {
1215
this._buffer = null;
1316
this._offset = 0;
1417
}
18+
Util.inherits(PacketWriter, EventEmitter);
1519

1620
PacketWriter.prototype.toBuffer = function toBuffer(parser) {
1721
if (!this._buffer) {
@@ -32,7 +36,8 @@ PacketWriter.prototype.toBuffer = function toBuffer(parser) {
3236
? length % MAX_PACKET_LENGTH
3337
: MAX_PACKET_LENGTH;
3438

35-
var packetNumber = parser.incrementPacketNumber();
39+
var packetNumber = parser.incrementPacketNumber(packet > 0);
40+
var packetOffset = this._offset;
3641

3742
this.writeUnsignedNumber(3, packetLength);
3843
this.writeUnsignedNumber(1, packetNumber);
@@ -41,6 +46,8 @@ PacketWriter.prototype.toBuffer = function toBuffer(parser) {
4146
var end = start + packetLength;
4247

4348
this.writeBuffer(buffer.slice(start, end));
49+
50+
this.emit('data', this._buffer.slice(packetOffset, this._offset));
4451
}
4552

4653
return this._buffer;

lib/protocol/Parser.js

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,20 @@ module.exports = Parser;
1111
function Parser(options) {
1212
options = options || {};
1313

14-
this._supportBigNumbers = options.config && options.config.supportBigNumbers;
15-
this._buffer = Buffer.alloc(0);
16-
this._nextBuffers = new BufferList();
17-
this._longPacketBuffers = new BufferList();
18-
this._offset = 0;
19-
this._packetEnd = null;
20-
this._packetHeader = null;
21-
this._packetOffset = null;
22-
this._onError = options.onError || function(err) { throw err; };
23-
this._onPacket = options.onPacket || function() {};
24-
this._nextPacketNumber = 0;
25-
this._encoding = 'utf-8';
26-
this._paused = false;
14+
this._supportBigNumbers = options.config && options.config.supportBigNumbers;
15+
this._buffer = Buffer.alloc(0);
16+
this._nextBuffers = new BufferList();
17+
this._expectedPacketNumber = 0;
18+
this._longPacketBuffers = new BufferList();
19+
this._offset = 0;
20+
this._packetEnd = null;
21+
this._packetHeader = null;
22+
this._packetOffset = null;
23+
this._onError = options.onError || function(err) { throw err; };
24+
this._onPacket = options.onPacket || function() {};
25+
this._nextPacketNumber = 0;
26+
this._encoding = 'utf-8';
27+
this._paused = false;
2728
}
2829

2930
Parser.prototype.write = function write(chunk) {
@@ -103,6 +104,16 @@ Parser.prototype.append = function append(chunk) {
103104
: null;
104105
};
105106

107+
Parser.prototype.isExpectedPacketNumber = function isExpectedPacketNumber(num) {
108+
if (this._expectedPacketNumber === this._nextPacketNumber) {
109+
return this._expectedPacketNumber === num;
110+
} else if (this._expectedPacketNumber < this._nextPacketNumber) {
111+
return this._expectedPacketNumber <= num && this._nextPacketNumber >= num;
112+
} else {
113+
return this._expectedPacketNumber <= num || this._nextPacketNumber >= num;
114+
}
115+
};
116+
106117
Parser.prototype.pause = function() {
107118
this._paused = true;
108119
};
@@ -345,15 +356,20 @@ Parser.prototype.reachedPacketEnd = function() {
345356
return this._offset === this._packetEnd;
346357
};
347358

348-
Parser.prototype.incrementPacketNumber = function() {
359+
Parser.prototype.incrementPacketNumber = function incrementPacketNumber(isContinuation) {
349360
var currentPacketNumber = this._nextPacketNumber;
350361
this._nextPacketNumber = (this._nextPacketNumber + 1) % 256;
351362

363+
if (!isContinuation) {
364+
this._expectedPacketNumber = this._nextPacketNumber;
365+
}
366+
352367
return currentPacketNumber;
353368
};
354369

355370
Parser.prototype.resetPacketNumber = function() {
356-
this._nextPacketNumber = 0;
371+
this._expectedPacketNumber = 0;
372+
this._nextPacketNumber = 0;
357373
};
358374

359375
Parser.prototype.packetLength = function packetLength() {
@@ -466,7 +482,7 @@ Parser.prototype._tryReadPacketHeader = function _tryReadPacketHeader() {
466482
this.parseUnsignedNumber(1)
467483
);
468484

469-
if (this._packetHeader.number !== this._nextPacketNumber) {
485+
if (!this.isExpectedPacketNumber(this._packetHeader.number)) {
470486
var err = new Error(
471487
'Packets out of order. Got: ' + this._packetHeader.number + ' ' +
472488
'Expected: ' + this._nextPacketNumber

lib/protocol/Protocol.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,14 @@ Protocol.prototype._parsePacketDebug = function _parsePacketDebug(packet) {
301301

302302
Protocol.prototype._emitPacket = function(packet) {
303303
var packetWriter = new PacketWriter();
304+
var protocol = this;
305+
306+
packetWriter.on('data', function (data) {
307+
protocol.emit('data', data);
308+
});
309+
304310
packet.write(packetWriter);
305-
this.emit('data', packetWriter.toBuffer(this._parser));
311+
packetWriter.toBuffer(this._parser);
306312

307313
if (this._config.debug) {
308314
this._debugPacket(false, packet);

lib/protocol/sequences/Sequence.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ Sequence.prototype._packetToError = function(packet) {
5151
err.sqlMessage = packet.message;
5252
err.sqlState = packet.sqlState;
5353

54+
// fatal sql state
55+
if (packet.sqlState === '08S01') {
56+
err.fatal = true;
57+
}
58+
5459
return err;
5560
};
5661

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
var assert = require('assert');
2+
var common = require('../../common');
3+
var crypto = require('crypto');
4+
5+
if (process.platform === 'win32') {
6+
common.skipTest('windows sockets close immediately');
7+
}
8+
9+
common.getTestConnection(function (err, conn) {
10+
assert.ifError(err);
11+
12+
conn.query('SHOW VARIABLES WHERE Variable_name = ?', ['max_allowed_packet'], function (err, rows) {
13+
assert.ifError(err);
14+
assert.strictEqual(rows.length, 1);
15+
16+
var maxAllowedPacket = Number(rows[0].Value);
17+
assert.ok(maxAllowedPacket > 0);
18+
19+
var length = maxAllowedPacket;
20+
var random = crypto.pseudoRandomBytes || crypto.randomBytes; // Depends on node.js version
21+
22+
random(length, function (err, buf) {
23+
assert.ifError(err);
24+
conn.query('SELECT ?', [buf], function (err) {
25+
assert.ok(err);
26+
assert.strictEqual(err.code, 'ER_NET_PACKET_TOO_LARGE');
27+
assert.strictEqual(err.fatal, true);
28+
});
29+
});
30+
});
31+
});

0 commit comments

Comments
 (0)