diff options
author | isaacs <i@izs.me> | 2013-05-24 17:16:08 -0700 |
---|---|---|
committer | isaacs <i@izs.me> | 2013-05-27 14:46:52 -0700 |
commit | ba048e72b02e17f0c73e0dcb7d37e76a03327c5a (patch) | |
tree | be9aa3f1f745db25ce2fa12116acf07ac48683cd /lib | |
parent | 9c7078cea2b719defbb6519d10a14ab15e733822 (diff) | |
parent | f904d614bf62d4bbf9c3adffb485f84d5c77c2d8 (diff) | |
download | android-node-v8-ba048e72b02e17f0c73e0dcb7d37e76a03327c5a.tar.gz android-node-v8-ba048e72b02e17f0c73e0dcb7d37e76a03327c5a.tar.bz2 android-node-v8-ba048e72b02e17f0c73e0dcb7d37e76a03327c5a.zip |
Merge remote-tracking branch 'ry/v0.10'
Conflicts:
AUTHORS
ChangeLog
configure
deps/uv/ChangeLog
deps/uv/src/unix/darwin.c
deps/uv/src/unix/stream.c
deps/uv/src/version.c
deps/v8/src/isolate.cc
deps/v8/src/version.cc
lib/http.js
src/node_version.h
Diffstat (limited to 'lib')
-rw-r--r-- | lib/_http_client.js | 7 | ||||
-rw-r--r-- | lib/_http_outgoing.js | 5 | ||||
-rw-r--r-- | lib/_http_server.js | 7 | ||||
-rw-r--r-- | lib/buffer.js | 3 | ||||
-rw-r--r-- | lib/net.js | 14 | ||||
-rw-r--r-- | lib/timers.js | 108 | ||||
-rw-r--r-- | lib/tls.js | 9 |
7 files changed, 142 insertions, 11 deletions
diff --git a/lib/_http_client.js b/lib/_http_client.js index 339a5c785d..e02cb4f40c 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -25,6 +25,9 @@ var EventEmitter = require('events').EventEmitter; var HTTPParser = process.binding('http_parser').HTTPParser; var assert = require('assert').ok; +// an empty buffer for UPGRADE/CONNECT bodyHead compatibility +var emptyBuffer = new Buffer(0); + var common = require('_http_common'); var httpSocketSetup = common.httpSocketSetup; @@ -273,7 +276,9 @@ function socketOnData(d, start, end) { socket.removeListener('close', socketCloseListener); socket.removeListener('error', socketErrorListener); - req.emit(eventName, res, socket, bodyHead); + socket.unshift(bodyHead); + + req.emit(eventName, res, socket, emptyBuffer); req.emit('close'); } else { // Got Upgrade header or CONNECT method, but have no handler. diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index 7248e5a135..8455b91603 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -402,7 +402,10 @@ OutgoingMessage.prototype.write = function(chunk, encoding) { throw new TypeError('first argument must be a string or Buffer'); } - if (chunk.length === 0) return false; + + // If we get an empty string or buffer, then just do nothing, and + // signal the user to keep writing. + if (chunk.length === 0) return true; var len, ret; if (this.chunkedEncoding) { diff --git a/lib/_http_server.js b/lib/_http_server.js index bbbcb371d4..9d1adc6320 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -25,6 +25,9 @@ var EventEmitter = require('events').EventEmitter; var HTTPParser = process.binding('http_parser').HTTPParser; var assert = require('assert').ok; +// an empty buffer for UPGRADE/CONNECT bodyHead compatibility +var emptyBuffer = new Buffer(0); + var common = require('_http_common'); var parsers = common.parsers; var freeParser = common.freeParser; @@ -356,7 +359,9 @@ function connectionListener(socket) { if (EventEmitter.listenerCount(self, eventName) > 0) { // This is start + byteParsed var bodyHead = d.slice(start + bytesParsed, end); - self.emit(eventName, req, req.socket, bodyHead); + + socket.unshift(bodyHead); + self.emit(eventName, req, req.socket, emptyBuffer); } else { // Got upgrade header or CONNECT method, but have no handler. socket.destroy(); diff --git a/lib/buffer.js b/lib/buffer.js index e5fa44d928..48c69f3f2b 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -339,6 +339,9 @@ Buffer.prototype.write = function(string, offset, length, encoding) { } encoding = String(encoding || 'utf8').toLowerCase(); + if (string.length > 0 && (length < 0 || offset < 0)) + throw new RangeError('attempt to write beyond buffer bounds'); + var ret; switch (encoding) { case 'hex': diff --git a/lib/net.js b/lib/net.js index e248bdfb3c..4ada1dc787 100644 --- a/lib/net.js +++ b/lib/net.js @@ -298,7 +298,7 @@ Socket.prototype.listen = function() { Socket.prototype.setTimeout = function(msecs, callback) { if (msecs > 0 && !isNaN(msecs) && isFinite(msecs)) { timers.enroll(this, msecs); - timers.active(this); + timers._unrefActive(this); if (callback) { this.once('timeout', callback); } @@ -472,7 +472,7 @@ function onread(buffer, offset, length) { var self = handle.owner; assert(handle === self._handle, 'handle != self._handle'); - timers.active(self); + timers._unrefActive(self); var end = offset + length; debug('onread', process._errno, offset, length, end); @@ -603,7 +603,7 @@ Socket.prototype._writeGeneric = function(writev, data, encoding, cb) { this._pendingData = null; this._pendingEncoding = ''; - timers.active(this); + timers._unrefActive(this); if (!this._handle) { this._destroy(new Error('This socket is closed.'), cb); @@ -744,7 +744,7 @@ function afterWrite(status, handle, req) { return; } - timers.active(self); + timers._unrefActive(self); if (self !== process.stderr && self !== process.stdout) debug('afterWrite call cb'); @@ -825,7 +825,7 @@ Socket.prototype.connect = function(options, cb) { self.once('connect', cb); } - timers.active(this); + timers._unrefActive(this); self._connecting = true; self.writable = true; @@ -858,7 +858,7 @@ Socket.prototype.connect = function(options, cb) { self._destroy(); }); } else { - timers.active(self); + timers._unrefActive(self); addressType = addressType || 4; @@ -905,7 +905,7 @@ function afterConnect(status, handle, req, readable, writable) { if (status == 0) { self.readable = readable; self.writable = writable; - timers.active(self); + timers._unrefActive(self); self.emit('connect'); diff --git a/lib/timers.js b/lib/timers.js index 1412928c51..8911e2ebf7 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -368,3 +368,111 @@ exports.clearImmediate = function(immediate) { process._needImmediateCallback = false; } }; + + +// Internal APIs that need timeouts should use timers._unrefActive isntead of +// timers.active as internal timeouts shouldn't hold the loop open + +var unrefList, unrefTimer; + + +function unrefTimeout() { + var now = Date.now(); + + debug('unrefTimer fired'); + + var first; + while (first = L.peek(unrefList)) { + var diff = now - first._idleStart; + + if (diff < first._idleTimeout) { + diff = first._idleTimeout - diff; + unrefTimer.start(diff, 0); + unrefTimer.when = now + diff; + debug('unrefTimer rescheudling for later'); + return; + } + + L.remove(first); + + var domain = first.domain; + + if (!first._onTimeout) continue; + if (domain && domain._disposed) continue; + + try { + if (domain) domain.enter(); + var threw = true; + debug('unreftimer firing timeout'); + first._onTimeout(); + threw = false; + if (domain) domain.exit(); + } finally { + if (threw) process.nextTick(unrefTimeout); + } + } + + debug('unrefList is empty'); + unrefTimer.when = -1; +} + + +exports._unrefActive = function(item) { + var msecs = item._idleTimeout; + if (!msecs || msecs < 0) return; + assert(msecs >= 0); + + L.remove(item); + + if (!unrefList) { + debug('unrefList initialized'); + unrefList = {}; + L.init(unrefList); + + debug('unrefTimer initialized'); + unrefTimer = new Timer(); + unrefTimer.unref(); + unrefTimer.when = -1; + unrefTimer.ontimeout = unrefTimeout; + } + + var now = Date.now(); + item._idleStart = now; + + if (L.isEmpty(unrefList)) { + debug('unrefList empty'); + L.append(unrefList, item); + + unrefTimer.start(msecs, 0); + unrefTimer.when = now + msecs; + debug('unrefTimer scheduled'); + return; + } + + var when = now + msecs; + + debug('unrefList find where we can insert'); + + var cur, them; + + for (cur = unrefList._idlePrev; cur != unrefList; cur = cur._idlePrev) { + them = cur._idleStart + cur._idleTimeout; + + if (when < them) { + debug('unrefList inserting into middle of list'); + + L.append(cur, item); + + if (unrefTimer.when > when) { + debug('unrefTimer is scheduled to fire too late, reschedule'); + unrefTimer.start(msecs, 0); + unrefTimer.when = when; + } + + return; + } + } + + debug('unrefList append to end'); + L.append(unrefList, item); +}; diff --git a/lib/tls.js b/lib/tls.js index cc71bd9761..4f170324b9 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -249,6 +249,7 @@ function CryptoStream(pair, options) { this._pendingEncoding = ''; this._pendingCallback = null; this._doneFlag = false; + this._retryAfterPartial = false; this._resumingSession = false; this._reading = true; this._destroyed = false; @@ -357,7 +358,13 @@ CryptoStream.prototype._write = function write(data, encoding, cb) { return cb(null); } - assert(written === 0 || written === -1); + if (written !== 0 && written !== -1) { + assert(!this._retryAfterPartial); + this._retryAfterPartial = true; + this._write(data.slice(written), encoding, cb); + this._retryAfterPartial = false; + return; + } } else { debug('cleartext.write queue is full'); |