diff --git a/doc/api/net.markdown b/doc/api/net.markdown index 0afcffc75..816050ae8 100644 --- a/doc/api/net.markdown +++ b/doc/api/net.markdown @@ -13,7 +13,9 @@ automatically set as a listener for the ['connection'][] event. `options` is an object with the following defaults: - { allowHalfOpen: false + { + allowHalfOpen: false, + pauseOnConnect: false } If `allowHalfOpen` is `true`, then the socket won't automatically send a FIN @@ -21,6 +23,11 @@ packet when the other end of the socket sends a FIN packet. The socket becomes non-readable, but still writable. You should call the `end()` method explicitly. See ['end'][] event for more information. +If `pauseOnConnect` is `true`, then the socket associated with each incoming +connection will be paused, and no data will be read from its handle. This allows +connections to be passed between processes without any data being read by the +original process. To begin reading data from a paused socket, call `resume()`. + Here is an example of an echo server which listens for connections on port 8124: diff --git a/doc/api/smalloc.markdown b/doc/api/smalloc.markdown index e407bb19c..ff905714e 100644 --- a/doc/api/smalloc.markdown +++ b/doc/api/smalloc.markdown @@ -48,6 +48,10 @@ possible options are listed in `smalloc.Types`. Example usage: // { '0': 0, '1': 0.1, '2': 0.2 } +It is not possible to freeze, seal and prevent extensions of objects with +external data using `Object.freeze`, `Object.seal` and +`Object.preventExtensions` respectively. + ### smalloc.copyOnto(source, sourceStart, dest, destStart, copyLength); * `source` {Object} with external array allocation @@ -105,8 +109,10 @@ careful. Cryptic errors may arise in applications that are difficult to trace. smalloc.copyOnto(b, 2, a, 0, 2); // now results in: - // Error: source has no external array data + // RangeError: copy_length > source_length +After `dispose()` is called object still behaves as one with external data, for +example `smalloc.hasExternalData()` returns `true`. `dispose()` does not support Buffers, and will throw if passed. ### smalloc.hasExternalData(obj) diff --git a/lib/net.js b/lib/net.js index 005f339c2..34de98bc3 100644 --- a/lib/net.js +++ b/lib/net.js @@ -180,8 +180,16 @@ function Socket(options) { // if we have a handle, then start the flow of data into the // buffer. if not, then this will happen when we connect - if (this._handle && options.readable !== false) - this.read(0); + if (this._handle && options.readable !== false) { + if (options.pauseOnCreate) { + // stop the handle from reading and pause the stream + this._handle.reading = false; + this._handle.readStop(); + this._readableState.flowing = false; + } else { + this.read(0); + } + } } util.inherits(Socket, stream.Duplex); @@ -1024,6 +1032,7 @@ function Server(/* [ options, ] listener */) { this._slaves = []; this.allowHalfOpen = options.allowHalfOpen || false; + this.pauseOnConnect = !!options.pauseOnConnect; } util.inherits(Server, events.EventEmitter); exports.Server = Server; @@ -1287,7 +1296,8 @@ function onconnection(err, clientHandle) { var socket = new Socket({ handle: clientHandle, - allowHalfOpen: self.allowHalfOpen + allowHalfOpen: self.allowHalfOpen, + pauseOnCreate: self.pauseOnConnect }); socket.readable = socket.writable = true; diff --git a/lib/path.js b/lib/path.js index a39031e21..6af430ec4 100644 --- a/lib/path.js +++ b/lib/path.js @@ -164,9 +164,10 @@ if (isWindows) { !resolvedAbsolute).join('\\'); // If device is a drive letter, we'll normalize to lower case. - if (resolvedDevice && resolvedDevice.charAt(1) === ':') + if (resolvedDevice && resolvedDevice.charAt(1) === ':') { resolvedDevice = resolvedDevice[0].toLowerCase() + resolvedDevice.substr(1); + } return (resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail) || '.'; diff --git a/test/simple/test-net-server-pause-on-connect.js b/test/simple/test-net-server-pause-on-connect.js new file mode 100644 index 000000000..3a8255e8f --- /dev/null +++ b/test/simple/test-net-server-pause-on-connect.js @@ -0,0 +1,59 @@ +// 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. + +var common = require('../common'); +var assert = require('assert'); +var net = require('net'); +var msg = 'test'; +var stopped = true; +var server1 = net.createServer({pauseOnConnect: true}, function(socket) { + socket.on('data', function(data) { + if (stopped) { + assert(false, 'data event should not have happened yet'); + } + + assert.equal(data.toString(), msg, 'invalid data received'); + socket.end(); + server1.close(); + }); + + setTimeout(function() { + assert.equal(socket.bytesRead, 0, 'no data should have been read yet'); + socket.resume(); + stopped = false; + }, 3000); +}); + +var server2 = net.createServer({pauseOnConnect: false}, function(socket) { + socket.on('data', function(data) { + assert.equal(data.toString(), msg, 'invalid data received'); + socket.end(); + server2.close(); + }); +}); + +server1.listen(common.PORT, function() { + net.createConnection({port: common.PORT}).write(msg); +}); + +server2.listen(common.PORT + 1, function() { + net.createConnection({port: common.PORT + 1}).write(msg); +});