Skip to content

Commit

Permalink
Replace SecurePair with DuplexPair + TLSSocket
Browse files Browse the repository at this point in the history
  • Loading branch information
Antti Risteli committed Jan 15, 2018
1 parent d8e95ae commit 6d255fb
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 28 deletions.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -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"
Expand Down
9 changes: 1 addition & 8 deletions src/connection.js
Expand Up @@ -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);
Expand Down Expand Up @@ -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();
});
Expand Down Expand Up @@ -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) {
Expand Down
31 changes: 19 additions & 12 deletions 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;

Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
}
Expand All @@ -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;
}

Expand Down
8 changes: 0 additions & 8 deletions test/integration/connection-retry-test.js
Expand Up @@ -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) => {
Expand All @@ -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();
});
},
Expand Down

0 comments on commit 6d255fb

Please sign in to comment.