summaryrefslogtreecommitdiff
path: root/lib/tls.js
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2013-05-29 23:12:11 +0200
committerBen Noordhuis <info@bnoordhuis.nl>2013-05-29 23:12:11 +0200
commit28659aba37fc9136dad6181306696ce4a6d6ba3f (patch)
tree4e99c61affcf631f37c99d687f49a9a0c45d0247 /lib/tls.js
parentba048e72b02e17f0c73e0dcb7d37e76a03327c5a (diff)
parent9826b1549396ed05011d523ab5bf7a344b8cb8b6 (diff)
downloadandroid-node-v8-28659aba37fc9136dad6181306696ce4a6d6ba3f.tar.gz
android-node-v8-28659aba37fc9136dad6181306696ce4a6d6ba3f.tar.bz2
android-node-v8-28659aba37fc9136dad6181306696ce4a6d6ba3f.zip
Merge remote-tracking branch 'origin/v0.10'
Conflicts: deps/uv/ChangeLog deps/uv/src/unix/stream.c deps/uv/src/version.c lib/tls.js
Diffstat (limited to 'lib/tls.js')
-rw-r--r--lib/tls.js102
1 files changed, 75 insertions, 27 deletions
diff --git a/lib/tls.js b/lib/tls.js
index 4f170324b9..92ec579fb9 100644
--- a/lib/tls.js
+++ b/lib/tls.js
@@ -250,6 +250,8 @@ function CryptoStream(pair, options) {
this._pendingCallback = null;
this._doneFlag = false;
this._retryAfterPartial = false;
+ this._halfRead = false;
+ this._sslOutCb = null;
this._resumingSession = false;
this._reading = true;
this._destroyed = false;
@@ -278,8 +280,14 @@ function onCryptoStreamFinish() {
// NOTE: first call checks if client has sent us shutdown,
// second call enqueues shutdown into the BIO.
if (this.pair.ssl.shutdown() !== 1) {
+ if (this.pair.ssl && this.pair.ssl.error)
+ return this.pair.error();
+
this.pair.ssl.shutdown();
}
+
+ if (this.pair.ssl && this.pair.ssl.error)
+ return this.pair.error();
}
} else {
debug('encrypted.onfinish');
@@ -309,6 +317,19 @@ function onCryptoStreamEnd() {
}
+// NOTE: Called once `this._opposite` is set.
+CryptoStream.prototype.init = function init() {
+ var self = this;
+ this._opposite.on('sslOutEnd', function() {
+ if (self._sslOutCb) {
+ var cb = self._sslOutCb;
+ self._sslOutCb = null;
+ cb(null);
+ }
+ });
+};
+
+
CryptoStream.prototype._write = function write(data, encoding, cb) {
assert(this._pending === null);
@@ -337,28 +358,36 @@ CryptoStream.prototype._write = function write(data, encoding, cb) {
return cb(this.pair.error(true));
}
+ // Whole buffer was written
+ if (written === data.length) {
+ if (this === this.pair.cleartext) {
+ debug('cleartext.write succeed with ' + written + ' bytes');
+ } else {
+ debug('encrypted.write succeed with ' + written + ' bytes');
+ }
+
+ // Invoke callback only when all data read from opposite stream
+ if (this._opposite._halfRead) {
+ assert(this._sslOutCb === null);
+ this._sslOutCb = cb;
+ } else {
+ cb(null);
+ }
+ }
+
// Force SSL_read call to cycle some states/data inside OpenSSL
this.pair.cleartext.read(0);
// Cycle encrypted data
- if (this.pair.encrypted._internallyPendingBytes()) {
+ if (this.pair.encrypted._internallyPendingBytes())
this.pair.encrypted.read(0);
- }
// Get NPN and Server name when ready
this.pair.maybeInitFinished();
- // Whole buffer was written
if (written === data.length) {
- if (this === this.pair.cleartext) {
- debug('cleartext.write succeed with %d bytes', data.length);
- } else {
- debug('encrypted.write succeed with %d bytes', data.length);
- }
-
- return cb(null);
- }
- if (written !== 0 && written !== -1) {
+ return;
+ } else if (written !== 0 && written !== -1) {
assert(!this._retryAfterPartial);
this._retryAfterPartial = true;
this._write(data.slice(written), encoding, cb);
@@ -460,25 +489,42 @@ CryptoStream.prototype._read = function read(size) {
this._opposite._done();
// EOF
- return this.push(null);
+ this.push(null);
+ } else {
+ // Bail out
+ this.push('');
}
-
- // Bail out
- return this.push('');
+ } else {
+ // Give them requested data
+ if (this.ondata) {
+ var self = this;
+ this.ondata(pool, start, start + bytesRead);
+
+ // Consume data automatically
+ // simple/test-https-drain fails without it
+ process.nextTick(function() {
+ self.read(bytesRead);
+ });
+ }
+ this.push(pool.slice(start, start + bytesRead));
}
- // Give them requested data
- if (this.ondata) {
- var self = this;
- this.ondata(pool, start, start + bytesRead);
+ // Let users know that we've some internal data to read
+ var halfRead = this._internallyPendingBytes() !== 0;
- // Consume data automatically
- // simple/test-https-drain fails without it
- process.nextTick(function() {
- self.read(bytesRead);
- });
+ // Smart check to avoid invoking 'sslOutEnd' in the most of the cases
+ if (this._halfRead !== halfRead) {
+ this._halfRead = halfRead;
+
+ // Notify listeners about internal data end
+ if (this === this.pair.cleartext) {
+ debug('cleartext.sslOutEnd');
+ } else {
+ debug('encrypted.sslOutEnd');
+ }
+
+ this.emit('sslOutEnd');
}
- return this.push(pool.slice(start, start + bytesRead));
};
@@ -590,7 +636,7 @@ CryptoStream.prototype.destroySoon = function(err) {
if (this.writable)
this.end();
- if (this._writableState.finished)
+ if (this._writableState.finished && this._opposite._ended)
this.destroy();
else
this.once('finish', this.destroy);
@@ -871,6 +917,8 @@ function SecurePair(credentials, isServer, requestCert, rejectUnauthorized,
/* Let streams know about each other */
this.cleartext._opposite = this.encrypted;
this.encrypted._opposite = this.cleartext;
+ this.cleartext.init();
+ this.encrypted.init();
process.nextTick(function() {
/* The Connection may be destroyed by an abort call */