Skip to content

Commit 7c06666

Browse files
Merge pull request #396 from sidorares/connection-timeout
added connect timeout event and tests
2 parents 5f10b4a + 75e7091 commit 7c06666

File tree

3 files changed

+58
-16
lines changed

3 files changed

+58
-16
lines changed

lib/connection.js

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
var net = require('net');
1+
var Net = require('net');
22
var util = require('util');
3-
var tls = require('tls');
3+
var Tls = require('tls');
4+
var Timers = require('timers');
45
var EventEmitter = require('events').EventEmitter;
56
var Queue = require('double-ended-queue');
67

@@ -30,9 +31,9 @@ function Connection (opts)
3031

3132
if (!opts.config.stream) {
3233
if (opts.config.socketPath) {
33-
this.stream = net.connect(opts.config.socketPath);
34+
this.stream = Net.connect(opts.config.socketPath);
3435
} else {
35-
this.stream = net.connect(opts.config.port, opts.config.host);
36+
this.stream = Net.connect(opts.config.port, opts.config.host);
3637
}
3738
} else {
3839
// if stream is a function, treat it as "stream agent / factory"
@@ -74,19 +75,22 @@ function Connection (opts)
7475
this.threadId = null;
7576
this._handshakePacket = null;
7677
this._fatalError = null;
77-
78+
this._protocolError = null;
7879
this._outOfOrderPackets = [];
7980

80-
this.stream.once('error', function (err) {
81-
connection._handleNetworkError(err);
82-
});
81+
this.stream.once('error', connection._handleNetworkError.bind(this));
8382

8483
// see https://gist.github.com/khoomeister/4985691#use-that-instead-of-bind
8584
this.packetParser = new PacketParser(function (p) { connection.handlePacket(p); });
85+
8686
this.stream.on('data', function (data) {
87+
if (connection.connectTimeout) {
88+
Timers.clearTimeout(connection.connectTimeout);
89+
connection.connectTimeout = null;
90+
}
8791
connection.packetParser.execute(data);
8892
});
89-
this._protocolError = null;
93+
9094
this.stream.on('end', function () {
9195
// we need to set this flag everywhere where we want connection to close
9296
if (connection._closing) {
@@ -119,6 +123,11 @@ function Connection (opts)
119123
// most common example: "Too many connections" error ( packet is sent immediately on connection attempt, we don't know server encoding yet)
120124
// will be overwrittedn with actial encoding value as soon as server handshake packet is received
121125
this.serverEncoding = 'utf8';
126+
127+
if (this.config.connectTimeout) {
128+
var timeoutHandler = this._handleTimeoutError.bind(this);
129+
this.connectTimeout = Timers.setTimeout(timeoutHandler, this.config.connectTimeout);
130+
}
122131
}
123132
util.inherits(Connection, EventEmitter);
124133

@@ -139,6 +148,21 @@ Connection.prototype._handleNetworkError = function (err) {
139148
connection._fatalError = err;
140149
};
141150

151+
Connection.prototype._handleTimeoutError = function () {
152+
if (this.stream) {
153+
Timers.clearTimeout(this.connectTimeout);
154+
this.connectTimeout = null;
155+
this.stream.destroy();
156+
}
157+
158+
var err = new Error('connect ETIMEDOUT');
159+
err.errorno = 'ETIMEDOUT';
160+
err.code = 'ETIMEDOUT';
161+
err.syscall = 'connect';
162+
163+
this._handleNetworkError(err);
164+
};
165+
142166
// notify all commands in the queue and bubble error as connection "error"
143167
// called on stream error or unexpected termination
144168
Connection.prototype._notifyError = function (err) {
@@ -191,15 +215,15 @@ Connection.prototype.writePacket = function (packet) {
191215
this.write(packet.buffer);
192216
};
193217

194-
if (tls.TLSSocket) {
218+
if (Tls.TLSSocket) {
195219
// 0.11+ environment
196220
Connection.prototype.startTLS = function _startTLS (onSecure) {
197221
if (this.config.debug) {
198222
console.log('Upgrading connection to TLS');
199223
}
200224
var connection = this;
201225
var stream = this.stream;
202-
var secureContext = tls.createSecureContext({
226+
var secureContext = Tls.createSecureContext({
203227
ca : this.config.ssl.ca,
204228
cert : this.config.ssl.cert,
205229
ciphers : this.config.ssl.ciphers,
@@ -209,7 +233,7 @@ if (tls.TLSSocket) {
209233

210234
var rejectUnauthorized = this.config.ssl.rejectUnauthorized;
211235
var secureEstablished = false;
212-
var secureSocket = new tls.TLSSocket(connection.stream, {
236+
var secureSocket = new Tls.TLSSocket(connection.stream, {
213237
rejectUnauthorized : rejectUnauthorized,
214238
requestCert : true,
215239
secureContext : secureContext,
@@ -244,7 +268,6 @@ if (tls.TLSSocket) {
244268
console.log('Upgrading connection to TLS');
245269
}
246270
var connection = this;
247-
var tls = require('tls');
248271
var crypto = require('crypto');
249272
var config = this.config;
250273
var stream = this.stream;
@@ -256,7 +279,7 @@ if (tls.TLSSocket) {
256279
ca : config.ssl.ca,
257280
ciphers : config.ssl.ciphers
258281
});
259-
var securePair = tls.createSecurePair(credentials, false, true, rejectUnauthorized);
282+
var securePair = Tls.createSecurePair(credentials, false, true, rejectUnauthorized);
260283

261284
if (stream.ondata) {
262285
stream.ondata = null;
@@ -278,7 +301,7 @@ if (tls.TLSSocket) {
278301

279302
Connection.prototype.pipe = function () {
280303
var connection = this;
281-
if (this.stream instanceof net.Stream) {
304+
if (this.stream instanceof Net.Stream) {
282305
this.stream.ondata = function (data, start, end) {
283306
connection.packetParser.execute(data, start, end);
284307
};

test/common.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ module.exports.createConnection = function (args, callback) {
5959
}
6060

6161
var params = {
62-
host: config.host,
62+
host: args.host || config.host,
6363
rowsAsArray: args.rowsAsArray,
6464
user: (args && args.user) || config.user,
6565
password: (args && args.password) || config.password,
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
var common = require('../../common');
2+
var connection = common.createConnection({
3+
host: 'www.google.com'
4+
});
5+
var assert = require('assert');
6+
7+
var errorCount = 0;
8+
var error = null;
9+
10+
11+
connection.on('error', function (err) {
12+
errorCount++;
13+
error = err;
14+
});
15+
16+
process.on('exit', function () {
17+
assert.equal(errorCount, 1);
18+
assert.equal(error.code, 'ETIMEDOUT');
19+
});

0 commit comments

Comments
 (0)