From: koichik Date: Mon, 9 Jan 2012 01:18:39 +0000 (+0100) Subject: net: make connect() accept options X-Git-Tag: v0.7.0~45 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=70033bd96098fd230fcb45287f4664115bc0ec63;p=platform%2Fupstream%2Fnodejs.git net: make connect() accept options This makes API even with tls.connect(). Refs #1983. See also: http://groups.google.com/group/nodejs-dev/msg/3b6dbcc4a9a82d99 Fixes #2487. --- diff --git a/doc/api/net.markdown b/doc/api/net.markdown index 1e3dfbd..e3e3195 100644 --- a/doc/api/net.markdown +++ b/doc/api/net.markdown @@ -15,7 +15,7 @@ event. { allowHalfOpen: false } -If `allowHalfOpen` is `true`, then the socket won't automatically send FIN +If `allowHalfOpen` is `true`, then the socket won't automatically send a FIN 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_end_) event for more information. @@ -49,25 +49,29 @@ Use `nc` to connect to a UNIX domain socket server: nc -U /tmp/echo.sock -### net.connect(arguments...) -### net.createConnection(arguments...) +### net.connect(options, [cnnectionListener]) +### net.createConnection(options, [cnnectionListener]) -Construct a new socket object and opens a socket to the given location. When -the socket is established the ['connect'](#event_connect_) event will be +Constructs a new socket object and opens the socket to the given location. +When the socket is established, the ['connect'](#event_connect_) event will be emitted. -The arguments for these methods change the type of connection: +For TCP sockets, `options` argument should be an object which specifies: -* `net.connect(port, [host], [connectListener])` -* `net.createConnection(port, [host], [connectListener])` + - `port`: Port the client should connect to (Required). - Creates a TCP connection to `port` on `host`. If `host` is omitted, - `'localhost'` will be assumed. + - `host`: Host the client should connect to. Defaults to `'localhost'`. -* `net.connect(path, [connectListener])` -* `net.createConnection(path, [connectListener])` +For UNIX domain sockets, `options` argument should be an object which specifies: - Creates unix socket connection to `path`. + - `path`: Path the client should connect to (Required). + +Common options are: + + - `allowHalfOpen`: if `true`, the socket won't automatically send + a FIN packet when the other end of the socket sends a FIN packet. + Defaults to `false`. + See ['end'](#event_end_) event for more information. The `connectListener` parameter will be added as an listener for the ['connect'](#event_connect_) event. @@ -75,7 +79,8 @@ The `connectListener` parameter will be added as an listener for the Here is an example of a client of echo server as described previously: var net = require('net'); - var client = net.connect(8124, function() { //'connect' listener + var client = net.connect({port: 8124}, + function() { //'connect' listener console.log('client connected'); client.write('world!\r\n'); }); @@ -90,7 +95,22 @@ Here is an example of a client of echo server as described previously: To connect on the socket `/tmp/echo.sock` the second line would just be changed to - var client = net.connect('/tmp/echo.sock', function() { //'connect' listener + var client = net.connect({path: '/tmp/echo.sock'}, + +### net.connect(port, [host], [connectListener]) +### net.createConnection(port, [host], [connectListener]) + +Creates a TCP connection to `port` on `host`. If `host` is omitted, +`'localhost'` will be assumed. +The `connectListener` parameter will be added as an listener for the +['connect'](#event_connect_) event. + +### net.connect(path, [connectListener]) +### net.createConnection(path, [connectListener]) + +Creates unix socket connection to `path`. +The `connectListener` parameter will be added as an listener for the +['connect'](#event_connect_) event. --- diff --git a/lib/net.js b/lib/net.js index 5073295..3af9495 100644 --- a/lib/net.js +++ b/lib/net.js @@ -65,17 +65,47 @@ exports.createServer = function() { }; -exports.connect = exports.createConnection = function(port /* [host], [cb] */) { - var s; +// Target API: +// +// var s = net.connect({port: 80, host: 'google.com'}, function() { +// ... +// }); +// +// There are various forms: +// +// connect(options, [cb]) +// connect(port, [host], [cb]) +// connect(path, [cb]); +// +exports.connect = exports.createConnection = function() { + var args = normalizeConnectArgs(arguments); + var s = new Socket(args[0]); + return Socket.prototype.connect.apply(s, args); +}; - if (isPipeName(port)) { - s = new Socket({ handle: createPipe() }); +// Returns an array [options] or [options, cb] +// It is the same as the argument of Socket.prototype.connect(). +function normalizeConnectArgs(args) { + var options = {}; + + if (typeof args[0] === 'object') { + // connect(options, [cb]) + options = args[0]; + } else if (isPipeName(args[0])) { + // connect(path, [cb]); + options.path = args[0]; } else { - s = new Socket(); + // connect(port, [host], [cb]) + options.port = args[0]; + if (typeof args[1] === 'string') { + options.host = args[1]; + } } - return s.connect(port, arguments[1], arguments[2]); -}; + var cb = args[args.length - 1]; + return (typeof cb === 'function') ? [options, cb] : [options]; +} + /* called when creating new Socket, or when re-using a closed Socket */ function initSocketHandle(self) { @@ -525,24 +555,25 @@ function connect(self, address, port, addressType) { } -Socket.prototype.connect = function(port /* [host], [cb] */) { - var self = this; +Socket.prototype.connect = function(options, cb) { + if (typeof options !== 'object') { + // Old API: + // connect(port, [host], [cb]) + // connect(path, [cb]); + var args = normalizeConnectArgs(arguments); + return Socket.prototype.connect.apply(this, args); + } - var pipe = isPipeName(port); + var self = this; + var pipe = !!options.path; if (this.destroyed || !this._handle) { this._handle = pipe ? createPipe() : createTCP(); initSocketHandle(this); } - var host; - if (typeof arguments[1] === 'function') { - self.on('connect', arguments[1]); - } else { - host = arguments[1]; - if (typeof arguments[2] === 'function') { - self.on('connect', arguments[2]); - } + if (typeof cb === 'function') { + self.on('connect', cb); } timers.active(this); @@ -551,9 +582,14 @@ Socket.prototype.connect = function(port /* [host], [cb] */) { self.writable = true; if (pipe) { - connect(self, /*pipe_name=*/port); + connect(self, options.path); + + } else if (!options.host) { + debug('connect: missing host'); + connect(self, '127.0.0.1', options.port, 4); - } else if (typeof host == 'string') { + } else { + var host = options.host; debug('connect: find host ' + host); require('dns').lookup(host, function(err, ip, addressType) { // It's possible we were destroyed while looking this up. @@ -578,13 +614,9 @@ Socket.prototype.connect = function(port /* [host], [cb] */) { // expects remoteAddress to have a meaningful value ip = ip || (addressType === 4 ? '127.0.0.1' : '0:0:0:0:0:0:0:1'); - connect(self, ip, port, addressType); + connect(self, ip, options.port, addressType); } }); - - } else { - debug('connect: missing host'); - connect(self, '127.0.0.1', port, 4); } return self; }; diff --git a/test/simple/test-net-connect-options.js b/test/simple/test-net-connect-options.js new file mode 100644 index 0000000..8df692e --- /dev/null +++ b/test/simple/test-net-connect-options.js @@ -0,0 +1,58 @@ +// 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 serverGotEnd = false; +var clientGotEnd = false; + +var server = net.createServer({allowHalfOpen: true}, function(socket) { + socket.on('end', function() { + serverGotEnd = true; + }); + socket.end(); +}); + +server.listen(common.PORT, function() { + var client = net.connect({ + host: '127.0.0.1', + port: common.PORT, + allowHalfOpen: true + }, function() { + client.on('end', function() { + clientGotEnd = true; + setTimeout(function() { + assert(client.writable); + client.end(); + }, 10); + }); + client.on('close', function() { + server.close(); + }); + }); +}); + +process.on('exit', function() { + assert(serverGotEnd); + assert(clientGotEnd); +});