|
1 | 1 | var net = require('net');
|
2 | 2 | var util = require('util');
|
| 3 | +var tls = require('tls'); |
3 | 4 | var EventEmitter = require('events').EventEmitter;
|
4 | 5 | var Queue = require('double-ended-queue');
|
5 | 6 |
|
@@ -75,20 +76,8 @@ function Connection (opts)
|
75 | 76 |
|
76 | 77 | this._outOfOrderPackets = [];
|
77 | 78 |
|
78 |
| - this.stream.once('error', function (err) { |
79 |
| - err.fatal = true; |
80 |
| - // stop receiving packets |
81 |
| - connection.stream.removeAllListeners('data'); |
82 |
| - connection.addCommand = function (cmd) { |
83 |
| - if (cmd.onResult) { |
84 |
| - cmd.onResult(err); |
85 |
| - } else { |
86 |
| - connection.emit('error', err); |
87 |
| - } |
88 |
| - return; |
89 |
| - }; |
90 |
| - connection._notifyError(err); |
91 |
| - connection._fatalError = err; |
| 79 | + this.stream.once('error', function(err) { |
| 80 | + connection._handleNetworkError(err); |
92 | 81 | });
|
93 | 82 |
|
94 | 83 | // see https://gist.github.com/khoomeister/4985691#use-that-instead-of-bind
|
@@ -124,6 +113,23 @@ function Connection (opts)
|
124 | 113 | }
|
125 | 114 | util.inherits(Connection, EventEmitter);
|
126 | 115 |
|
| 116 | +Connection.prototype._handleNetworkError = function(err) { |
| 117 | + var connection = this; |
| 118 | + err.fatal = true; |
| 119 | + // stop receiving packets |
| 120 | + connection.stream.removeAllListeners('data'); |
| 121 | + connection.addCommand = function (cmd) { |
| 122 | + if (cmd.onResult) { |
| 123 | + cmd.onResult(err); |
| 124 | + } else { |
| 125 | + connection.emit('error', err); |
| 126 | + } |
| 127 | + return; |
| 128 | + }; |
| 129 | + connection._notifyError(err); |
| 130 | + connection._fatalError = err; |
| 131 | +}; |
| 132 | + |
127 | 133 | // notify all commands in the queue and bubble error as connection "error"
|
128 | 134 | // called on stream error or unexpected termination
|
129 | 135 | Connection.prototype._notifyError = function (err) {
|
@@ -175,42 +181,90 @@ Connection.prototype.writePacket = function (packet) {
|
175 | 181 | this.write(packet.buffer);
|
176 | 182 | };
|
177 | 183 |
|
178 |
| -Connection.prototype.startTLS = function _startTLS (onSecure) { |
179 |
| - if (this.config.debug) { |
180 |
| - console.log('Upgrading connection to TLS'); |
181 |
| - } |
182 |
| - var connection = this; |
183 |
| - var tls = require('tls'); |
184 |
| - var crypto = require('crypto'); |
185 |
| - var config = this.config; |
186 |
| - var stream = this.stream; |
187 |
| - var rejectUnauthorized = this.config.ssl.rejectUnauthorized; |
188 |
| - var credentials = crypto.createCredentials({ |
189 |
| - key : config.ssl.key, |
190 |
| - cert : config.ssl.cert, |
191 |
| - passphrase : config.ssl.passphrase, |
192 |
| - ca : config.ssl.ca, |
193 |
| - ciphers : config.ssl.ciphers |
194 |
| - }); |
195 |
| - var securePair = tls.createSecurePair(credentials, false, true, rejectUnauthorized); |
| 184 | +if (tls.TLSSocket) { |
| 185 | + // 0.11+ environment |
| 186 | + Connection.prototype.startTLS = function _startTLS (onSecure) { |
| 187 | + if (this.config.debug) { |
| 188 | + console.log('Upgrading connection to TLS'); |
| 189 | + } |
| 190 | + var connection = this; |
| 191 | + var stream = this.stream; |
| 192 | + var secureContext = tls.createSecureContext({ |
| 193 | + ca : this.config.ssl.ca, |
| 194 | + cert : this.config.ssl.cert, |
| 195 | + ciphers : this.config.ssl.ciphers, |
| 196 | + key : this.config.ssl.key, |
| 197 | + passphrase : this.config.ssl.passphrase |
| 198 | + }); |
196 | 199 |
|
197 |
| - if (stream.ondata) { |
198 |
| - stream.ondata = null; |
199 |
| - } |
200 |
| - stream.removeAllListeners('data'); |
201 |
| - stream.pipe(securePair.encrypted); |
202 |
| - securePair.encrypted.pipe(stream); |
203 |
| - securePair.cleartext.on('data', function (data) { |
204 |
| - connection.packetParser.execute(data); |
205 |
| - }); |
206 |
| - connection.write = function (buffer) { |
207 |
| - securePair.cleartext.write(buffer); |
| 200 | + var rejectUnauthorized = this.config.ssl.rejectUnauthorized; |
| 201 | + var secureEstablished = false; |
| 202 | + var secureSocket = new tls.TLSSocket(connection.stream, { |
| 203 | + rejectUnauthorized : rejectUnauthorized, |
| 204 | + requestCert : true, |
| 205 | + secureContext : secureContext, |
| 206 | + isServer : false |
| 207 | + }); |
| 208 | + |
| 209 | + // error handler for secure socket |
| 210 | + secureSocket.on('_tlsError', function(err) { |
| 211 | + if (secureEstablished) { |
| 212 | + connection._handleNetworkError(err); |
| 213 | + } else { |
| 214 | + onSecure(err); |
| 215 | + } |
| 216 | + }); |
| 217 | + |
| 218 | + secureSocket.on('secure', function() { |
| 219 | + secureEstablished = true; |
| 220 | + onSecure(rejectUnauthorized ? this.ssl.verifyError() : null); |
| 221 | + }); |
| 222 | + secureSocket.on('data', function (data) { |
| 223 | + connection.packetParser.execute(data); |
| 224 | + }); |
| 225 | + connection.write = function (buffer) { |
| 226 | + secureSocket.write(buffer); |
| 227 | + }; |
| 228 | + // start TLS communications |
| 229 | + secureSocket._start(); |
208 | 230 | };
|
209 |
| - securePair.on('secure', function () { |
210 |
| - onSecure(rejectUnauthorized ? this.ssl.verifyError() : null); |
211 |
| - }); |
212 |
| -}; |
| 231 | +} else { |
| 232 | + Connection.prototype.startTLS = function _startTLS (onSecure) { |
| 233 | + if (this.config.debug) { |
| 234 | + console.log('Upgrading connection to TLS'); |
| 235 | + } |
| 236 | + var connection = this; |
| 237 | + var tls = require('tls'); |
| 238 | + var crypto = require('crypto'); |
| 239 | + var config = this.config; |
| 240 | + var stream = this.stream; |
| 241 | + var rejectUnauthorized = this.config.ssl.rejectUnauthorized; |
| 242 | + var credentials = crypto.createCredentials({ |
| 243 | + key : config.ssl.key, |
| 244 | + cert : config.ssl.cert, |
| 245 | + passphrase : config.ssl.passphrase, |
| 246 | + ca : config.ssl.ca, |
| 247 | + ciphers : config.ssl.ciphers |
| 248 | + }); |
| 249 | + var securePair = tls.createSecurePair(credentials, false, true, rejectUnauthorized); |
213 | 250 |
|
| 251 | + if (stream.ondata) { |
| 252 | + stream.ondata = null; |
| 253 | + } |
| 254 | + stream.removeAllListeners('data'); |
| 255 | + stream.pipe(securePair.encrypted); |
| 256 | + securePair.encrypted.pipe(stream); |
| 257 | + securePair.cleartext.on('data', function (data) { |
| 258 | + connection.packetParser.execute(data); |
| 259 | + }); |
| 260 | + connection.write = function (buffer) { |
| 261 | + securePair.cleartext.write(buffer); |
| 262 | + }; |
| 263 | + securePair.on('secure', function () { |
| 264 | + onSecure(rejectUnauthorized ? this.ssl.verifyError() : null); |
| 265 | + }); |
| 266 | + }; |
| 267 | +} |
214 | 268 |
|
215 | 269 | Connection.prototype.pipe = function () {
|
216 | 270 | var connection = this;
|
|
0 commit comments