diff --git a/lib/tls.js b/lib/tls.js index df2afec53335..3ec126e3c419 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -335,7 +335,10 @@ CryptoStream.prototype._write = function write(data, encoding, cb) { written = this.pair.ssl.encIn(data, 0, data.length); } - var self = this; + // Handle and report errors + if (this.pair.ssl && this.pair.ssl.error) { + return cb(this.pair.error(true)); + } // Force SSL_read call to cycle some states/data inside OpenSSL this.pair.cleartext.read(0); @@ -345,11 +348,6 @@ CryptoStream.prototype._write = function write(data, encoding, cb) { this.pair.encrypted.read(0); } - // Handle and report errors - if (this.pair.ssl && this.pair.ssl.error) { - return cb(this.pair.error()); - } - // Get NPN and Server name when ready this.pair.maybeInitFinished(); @@ -919,7 +917,7 @@ SecurePair.prototype.destroy = function() { }; -SecurePair.prototype.error = function() { +SecurePair.prototype.error = function(returnOnly) { var err = this.ssl.error; this.ssl.error = null; @@ -929,14 +927,14 @@ SecurePair.prototype.error = function() { err.code = 'ECONNRESET'; } this.destroy(); - this.emit('error', err); + if (!returnOnly) this.emit('error', err); } else if (this._isServer && this._rejectUnauthorized && /peer did not return a certificate/.test(err.message)) { // Not really an error. this.destroy(); } else { - this.cleartext.emit('error', err); + if (!returnOnly) this.cleartext.emit('error', err); } return err; }; diff --git a/test/simple/test-tls-client-abort3.js b/test/simple/test-tls-client-abort3.js new file mode 100644 index 000000000000..72725187c4b2 --- /dev/null +++ b/test/simple/test-tls-client-abort3.js @@ -0,0 +1,68 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +if (!process.versions.openssl) { + console.error('Skipping because node compiled without OpenSSL.'); + process.exit(0); +} + +var common = require('../common'); +var common = require('../common'); +var tls = require('tls'); +var fs = require('fs'); +var assert = require('assert'); + +var options = { + key: fs.readFileSync(common.fixturesDir + '/test_key.pem'), + cert: fs.readFileSync(common.fixturesDir + '/test_cert.pem') +}; + +var gotError = 0, + gotRequest = 0, + connected = 0; + +var server = tls.createServer(options, function(c) { + gotRequest++; + c.on('data', function(data) { + console.log(data.toString()); + }); + + c.on('close', function() { + server.close(); + }); +}).listen(common.PORT, function() { + var c = tls.connect(common.PORT, { rejectUnauthorized: false }, function() { + connected++; + c.pair.ssl.shutdown(); + c.write('123'); + c.destroy(); + }); + + c.once('error', function() { + gotError++; + }); +}); + +process.once('exit', function() { + assert.equal(gotError, 1); + assert.equal(gotRequest, 1); + assert.equal(connected, 1); +});