From 6d255fbdaa2f9afd388617e6e34815cae95292a0 Mon Sep 17 00:00:00 2001 From: Antti Risteli Date: Mon, 15 Jan 2018 19:35:51 +0200 Subject: [PATCH] Replace SecurePair with DuplexPair + TLSSocket --- package.json | 1 + src/connection.js | 9 +------ src/message-io.js | 31 ++++++++++++++--------- test/integration/connection-retry-test.js | 8 ------ 4 files changed, 21 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index bca5b2668..3642c20db 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "babel-runtime": "^6.26.0", "big-number": "0.3.1", "bl": "^1.2.0", + "duplexpair": "1.0.1", "iconv-lite": "^0.4.11", "readable-stream": "^2.2.6", "sprintf": "0.1.5" diff --git a/src/connection.js b/src/connection.js index 9350ae2d7..f1b5156d5 100644 --- a/src/connection.js +++ b/src/connection.js @@ -357,7 +357,6 @@ class Connection extends EventEmitter { this.reset = this.reset.bind(this); this.socketClose = this.socketClose.bind(this); - this.socketEnd = this.socketEnd.bind(this); this.socketConnect = this.socketConnect.bind(this); this.socketError = this.socketError.bind(this); this.requestTimeout = this.requestTimeout.bind(this); @@ -692,12 +691,11 @@ class Connection extends EventEmitter { this.socket = socket; this.socket.on('error', this.socketError); - this.socket.on('close', this.socketClose); - this.socket.on('end', this.socketEnd); this.messageIo = new MessageIO(this.socket, this.config.options.packetSize, this.debug); this.messageIo.on('data', (data) => { this.dispatchEvent('data', data); }); this.messageIo.on('message', () => { this.dispatchEvent('message'); }); this.messageIo.on('secure', this.emit.bind(this, 'secure')); + this.messageIo.on('close', this.socketClose); this.socketConnect(); }); @@ -816,11 +814,6 @@ class Connection extends EventEmitter { this.dispatchEvent('socketConnect'); } - socketEnd() { - this.debug.log('socket ended'); - this.transitionTo(this.STATE.FINAL); - } - socketClose() { this.debug.log('connection to ' + this.config.server + ':' + this.config.options.port + ' closed'); if (this.state === this.STATE.REROUTING) { diff --git a/src/message-io.js b/src/message-io.js index 6c2a15c32..acbc884cd 100644 --- a/src/message-io.js +++ b/src/message-io.js @@ -1,5 +1,6 @@ const tls = require('tls'); const crypto = require('crypto'); +const DuplexPair = require('duplexpair'); const EventEmitter = require('events').EventEmitter; const Transform = require('readable-stream').Transform; @@ -67,6 +68,9 @@ module.exports = class MessageIO extends EventEmitter { this.emit('message'); } }); + this.packetStream.on('end', () => { + this.emit('close') + }) this.socket.pipe(this.packetStream); this.packetDataSize = this._packetSize - packetHeaderLength; @@ -84,23 +88,23 @@ module.exports = class MessageIO extends EventEmitter { startTls(credentialsDetails, hostname, trustServerCertificate) { const credentials = tls.createSecureContext ? tls.createSecureContext(credentialsDetails) : crypto.createCredentials(credentialsDetails); - this.securePair = tls.createSecurePair(credentials); + const duplexpair = new DuplexPair(); + this.securePair = { + cleartext: new tls.TLSSocket(duplexpair.socket1, { + secureContext: credentials, + rejectUnauthorized: false + }), + encrypted: duplexpair.socket2 + }; this.tlsNegotiationComplete = false; - this.securePair.on('secure', () => { + this.securePair.cleartext.on('secure', () => { const cipher = this.securePair.cleartext.getCipher(); if (!trustServerCertificate) { - let verifyError = this.securePair.ssl.verifyError(); - - // Verify that server's identity matches it's certificate's names - if (!verifyError) { - verifyError = tls.checkServerIdentity(hostname, this.securePair.cleartext.getPeerCertificate()); - } - - if (verifyError) { - this.securePair.destroy(); - this.socket.destroy(verifyError); + if (!this.tlsHandler.cleartext.authorized) { + this.securePair.cleartext.destroy() + this.socket.destroy(this.tlsHandler.cleartext.authorizationError); return; } } @@ -127,6 +131,9 @@ module.exports = class MessageIO extends EventEmitter { this.socket.pipe(this.securePair.encrypted); this.securePair.encrypted.pipe(this.socket); this.securePair.cleartext.pipe(this.packetStream); + this.socket.on('close', () => { + this.securePair.encrypted.end() + }) this.tlsNegotiationComplete = true; } diff --git a/test/integration/connection-retry-test.js b/test/integration/connection-retry-test.js index 860ab95f2..c02b6f716 100644 --- a/test/integration/connection-retry-test.js +++ b/test/integration/connection-retry-test.js @@ -74,8 +74,6 @@ exports['connection retry tests'] = { const config = getConfig(); config.options.connectTimeout = config.options.connectionRetryInterval / 2; - const clock = this.sinon.useFakeTimers(); - test.expect(1); this.sinon.stub(TransientErrorLookup.prototype, 'isTransientError', (error) => { @@ -88,17 +86,11 @@ exports['connection retry tests'] = { test.ok(false); }); - connection.on('errorMessage', () => { - // Forward clock past connectTimeout which is less than retry interval. - clock.tick(config.options.connectTimeout + 1); - }); - connection.on('connect', (err) => { test.ok(err); }); connection.on('end', (info) => { - clock.restore(); test.done(); }); },