From f6bce20e5e4e1fb26b1a35661c278f0b65569900 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 24 Sep 2011 05:07:35 +0200 Subject: buffers: handle bad length argument in constructor Coerce fractional, negative and non-numeric length arguments to numbers. Fractional numbers are rounded up, negative numbers and non-numeric values are set to zero. --- lib/buffer.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/buffer.js b/lib/buffer.js index 52e5e8052d..1ec89a2793 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -123,6 +123,15 @@ SlowBuffer.prototype.slice = function(start, end) { }; +function coerce(length) { + // Coerce length to a number (possibly NaN), round up + // in case it's fractional (e.g. 123.456) then do a + // double negate to coerce a NaN to 0. Easy, right? + length = ~~Math.ceil(+length); + return length < 0 ? 0 : length; +} + + // Buffer function Buffer(subject, encoding, offset) { @@ -134,14 +143,14 @@ function Buffer(subject, encoding, offset) { // Are we slicing? if (typeof offset === 'number') { - this.length = encoding; + this.length = coerce(encoding); this.parent = subject; this.offset = offset; } else { // Find the length switch (type = typeof subject) { case 'number': - this.length = subject; + this.length = coerce(subject); break; case 'string': @@ -149,7 +158,7 @@ function Buffer(subject, encoding, offset) { break; case 'object': // Assume object is an array - this.length = subject.length; + this.length = coerce(subject.length); break; default: -- cgit v1.2.1 From f9fec3a2d65580b7e39edc9afd5904cd4775c87c Mon Sep 17 00:00:00 2001 From: Eric Lovett Date: Fri, 23 Sep 2011 21:05:40 -0700 Subject: net: callback to socket.write should always be called asynchronously --- lib/net.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/net.js b/lib/net.js index be2bc58e33..4af00b4bcf 100644 --- a/lib/net.js +++ b/lib/net.js @@ -464,7 +464,9 @@ Socket.prototype._writeOut = function(data, encoding, fd, cb) { if (queuedData) { return false; } else { - if (cb) cb(); + if (cb) { + process.nextTick(cb); + } return true; } } -- cgit v1.2.1 From dea49e3d1900ffdc56a2077d1d701ec9e38bc58b Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Wed, 28 Sep 2011 17:43:20 -0700 Subject: net: Fix string-concat hot path bug Also removes functionality added in f9fec3a2d65580b7e39edc9afd5904cd4775c87c because it changes API. (That patch shouldn't have been added anyway.) --- lib/net.js | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/net.js b/lib/net.js index 4af00b4bcf..0e92ec17cc 100644 --- a/lib/net.js +++ b/lib/net.js @@ -349,11 +349,13 @@ Socket.prototype.write = function(data /* [encoding], [fd], [cb] */) { if (!this._writeQueueCallbacks[last]) { this._writeQueueCallbacks[last] = cb; } else { - // awful - this._writeQueueCallbacks[last] = function() { - this._writeQueueCallbacks[last](); - cb(); - }; + var original = this._writeQueueCallbacks[last]; + + if (Array.isArray(original)) { + original.push(cb); + } else { + this._writeQueueCallbacks[last] = [ original, cb ]; + } } } } else { @@ -465,7 +467,13 @@ Socket.prototype._writeOut = function(data, encoding, fd, cb) { return false; } else { if (cb) { - process.nextTick(cb); + if (Array.isArray(cb)) { + for (var i = 0; i < cb.length; i++) { + if (cb[i]) cb[i](); + } + } else { + cb(); + } } return true; } -- cgit v1.2.1 From 4cdf9d415864f124c3b17bf43731e40120f18ba0 Mon Sep 17 00:00:00 2001 From: koichik Date: Tue, 27 Sep 2011 18:25:10 +0900 Subject: tls: Improve TLS flow control Fixes #1775. --- lib/tls.js | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/tls.js b/lib/tls.js index f5bb3337fd..8adb7a2267 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -52,6 +52,7 @@ function CryptoStream(pair) { this.readable = this.writable = true; this._paused = false; + this._needDrain = false; this._pending = []; this._pendingCallbacks = []; this._pendingBytes = 0; @@ -86,7 +87,7 @@ CryptoStream.prototype.write = function(data /* , encoding, cb */) { data = new Buffer(data, encoding); } - debug('clearIn data'); + debug((this === this.pair.cleartext ? 'clear' : 'encrypted') + 'In data'); this._pending.push(data); this._pendingCallbacks.push(cb); @@ -95,7 +96,26 @@ CryptoStream.prototype.write = function(data /* , encoding, cb */) { this.pair._writeCalled = true; this.pair.cycle(); - return this._pendingBytes < 128 * 1024; + // In the following cases, write() should return a false, + // then this stream should eventually emit 'drain' event. + // + // 1. There are pending data more than 128k bytes. + // 2. A forward stream shown below is paused. + // A) EncryptedStream for CleartextStream.write(). + // B) CleartextStream for EncryptedStream.write(). + // + if (!this._needDrain) { + if (this._pendingBytes >= 128 * 1024) { + this._needDrain = true; + } else { + if (this === this.pair.cleartext) { + this._needDrain = this.pair.encrypted._paused; + } else { + this._needDrain = this.pair.cleartext._paused; + } + } + } + return !this._needDrain; }; @@ -380,11 +400,25 @@ CryptoStream.prototype._pull = function() { assert(rv === tmp.length); } - // If we've cleared all of incoming encrypted data, emit drain. - if (havePending && this._pending.length === 0) { - debug('drain'); - this.emit('drain'); - if (this.__destroyOnDrain) this.end(); + // If pending data has cleared, 'drain' event should be emitted + // after write() returns a false. + // Except when a forward stream shown below is paused. + // A) EncryptedStream for CleartextStream._pull(). + // B) CleartextStream for EncryptedStream._pull(). + // + if (this._needDrain && this._pending.length === 0) { + var paused; + if (this === this.pair.cleartext) { + paused = this.pair.encrypted._paused; + } else { + paused = this.pair.cleartext._paused; + } + if (!paused) { + debug('drain'); + process.nextTick(this.emit.bind(this, 'drain')); + this._needDrain = false; + if (this.__destroyOnDrain) this.end(); + } } }; -- cgit v1.2.1