Skip to content
This repository was archived by the owner on Apr 22, 2023. It is now read-only.

Commit 70033bd

Browse files
committed
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.
1 parent 0321adb commit 70033bd

File tree

3 files changed

+150
-40
lines changed

3 files changed

+150
-40
lines changed

doc/api/net.markdown

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ event.
1515
{ allowHalfOpen: false
1616
}
1717

18-
If `allowHalfOpen` is `true`, then the socket won't automatically send FIN
18+
If `allowHalfOpen` is `true`, then the socket won't automatically send a FIN
1919
packet when the other end of the socket sends a FIN packet. The socket becomes
2020
non-readable, but still writable. You should call the `end()` method explicitly.
2121
See ['end'](#event_end_) event for more information.
@@ -49,33 +49,38 @@ Use `nc` to connect to a UNIX domain socket server:
4949

5050
nc -U /tmp/echo.sock
5151

52-
### net.connect(arguments...)
53-
### net.createConnection(arguments...)
52+
### net.connect(options, [cnnectionListener])
53+
### net.createConnection(options, [cnnectionListener])
5454

55-
Construct a new socket object and opens a socket to the given location. When
56-
the socket is established the ['connect'](#event_connect_) event will be
55+
Constructs a new socket object and opens the socket to the given location.
56+
When the socket is established, the ['connect'](#event_connect_) event will be
5757
emitted.
5858

59-
The arguments for these methods change the type of connection:
59+
For TCP sockets, `options` argument should be an object which specifies:
6060

61-
* `net.connect(port, [host], [connectListener])`
62-
* `net.createConnection(port, [host], [connectListener])`
61+
- `port`: Port the client should connect to (Required).
6362

64-
Creates a TCP connection to `port` on `host`. If `host` is omitted,
65-
`'localhost'` will be assumed.
63+
- `host`: Host the client should connect to. Defaults to `'localhost'`.
6664

67-
* `net.connect(path, [connectListener])`
68-
* `net.createConnection(path, [connectListener])`
65+
For UNIX domain sockets, `options` argument should be an object which specifies:
6966

70-
Creates unix socket connection to `path`.
67+
- `path`: Path the client should connect to (Required).
68+
69+
Common options are:
70+
71+
- `allowHalfOpen`: if `true`, the socket won't automatically send
72+
a FIN packet when the other end of the socket sends a FIN packet.
73+
Defaults to `false`.
74+
See ['end'](#event_end_) event for more information.
7175

7276
The `connectListener` parameter will be added as an listener for the
7377
['connect'](#event_connect_) event.
7478

7579
Here is an example of a client of echo server as described previously:
7680

7781
var net = require('net');
78-
var client = net.connect(8124, function() { //'connect' listener
82+
var client = net.connect({port: 8124},
83+
function() { //'connect' listener
7984
console.log('client connected');
8085
client.write('world!\r\n');
8186
});
@@ -90,7 +95,22 @@ Here is an example of a client of echo server as described previously:
9095
To connect on the socket `/tmp/echo.sock` the second line would just be
9196
changed to
9297

93-
var client = net.connect('/tmp/echo.sock', function() { //'connect' listener
98+
var client = net.connect({path: '/tmp/echo.sock'},
99+
100+
### net.connect(port, [host], [connectListener])
101+
### net.createConnection(port, [host], [connectListener])
102+
103+
Creates a TCP connection to `port` on `host`. If `host` is omitted,
104+
`'localhost'` will be assumed.
105+
The `connectListener` parameter will be added as an listener for the
106+
['connect'](#event_connect_) event.
107+
108+
### net.connect(path, [connectListener])
109+
### net.createConnection(path, [connectListener])
110+
111+
Creates unix socket connection to `path`.
112+
The `connectListener` parameter will be added as an listener for the
113+
['connect'](#event_connect_) event.
94114

95115
---
96116

lib/net.js

Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,47 @@ exports.createServer = function() {
6565
};
6666

6767

68-
exports.connect = exports.createConnection = function(port /* [host], [cb] */) {
69-
var s;
68+
// Target API:
69+
//
70+
// var s = net.connect({port: 80, host: 'google.com'}, function() {
71+
// ...
72+
// });
73+
//
74+
// There are various forms:
75+
//
76+
// connect(options, [cb])
77+
// connect(port, [host], [cb])
78+
// connect(path, [cb]);
79+
//
80+
exports.connect = exports.createConnection = function() {
81+
var args = normalizeConnectArgs(arguments);
82+
var s = new Socket(args[0]);
83+
return Socket.prototype.connect.apply(s, args);
84+
};
7085

71-
if (isPipeName(port)) {
72-
s = new Socket({ handle: createPipe() });
86+
// Returns an array [options] or [options, cb]
87+
// It is the same as the argument of Socket.prototype.connect().
88+
function normalizeConnectArgs(args) {
89+
var options = {};
90+
91+
if (typeof args[0] === 'object') {
92+
// connect(options, [cb])
93+
options = args[0];
94+
} else if (isPipeName(args[0])) {
95+
// connect(path, [cb]);
96+
options.path = args[0];
7397
} else {
74-
s = new Socket();
98+
// connect(port, [host], [cb])
99+
options.port = args[0];
100+
if (typeof args[1] === 'string') {
101+
options.host = args[1];
102+
}
75103
}
76104

77-
return s.connect(port, arguments[1], arguments[2]);
78-
};
105+
var cb = args[args.length - 1];
106+
return (typeof cb === 'function') ? [options, cb] : [options];
107+
}
108+
79109

80110
/* called when creating new Socket, or when re-using a closed Socket */
81111
function initSocketHandle(self) {
@@ -525,24 +555,25 @@ function connect(self, address, port, addressType) {
525555
}
526556

527557

528-
Socket.prototype.connect = function(port /* [host], [cb] */) {
529-
var self = this;
558+
Socket.prototype.connect = function(options, cb) {
559+
if (typeof options !== 'object') {
560+
// Old API:
561+
// connect(port, [host], [cb])
562+
// connect(path, [cb]);
563+
var args = normalizeConnectArgs(arguments);
564+
return Socket.prototype.connect.apply(this, args);
565+
}
530566

531-
var pipe = isPipeName(port);
567+
var self = this;
568+
var pipe = !!options.path;
532569

533570
if (this.destroyed || !this._handle) {
534571
this._handle = pipe ? createPipe() : createTCP();
535572
initSocketHandle(this);
536573
}
537574

538-
var host;
539-
if (typeof arguments[1] === 'function') {
540-
self.on('connect', arguments[1]);
541-
} else {
542-
host = arguments[1];
543-
if (typeof arguments[2] === 'function') {
544-
self.on('connect', arguments[2]);
545-
}
575+
if (typeof cb === 'function') {
576+
self.on('connect', cb);
546577
}
547578

548579
timers.active(this);
@@ -551,9 +582,14 @@ Socket.prototype.connect = function(port /* [host], [cb] */) {
551582
self.writable = true;
552583

553584
if (pipe) {
554-
connect(self, /*pipe_name=*/port);
585+
connect(self, options.path);
586+
587+
} else if (!options.host) {
588+
debug('connect: missing host');
589+
connect(self, '127.0.0.1', options.port, 4);
555590

556-
} else if (typeof host == 'string') {
591+
} else {
592+
var host = options.host;
557593
debug('connect: find host ' + host);
558594
require('dns').lookup(host, function(err, ip, addressType) {
559595
// It's possible we were destroyed while looking this up.
@@ -578,13 +614,9 @@ Socket.prototype.connect = function(port /* [host], [cb] */) {
578614
// expects remoteAddress to have a meaningful value
579615
ip = ip || (addressType === 4 ? '127.0.0.1' : '0:0:0:0:0:0:0:1');
580616

581-
connect(self, ip, port, addressType);
617+
connect(self, ip, options.port, addressType);
582618
}
583619
});
584-
585-
} else {
586-
debug('connect: missing host');
587-
connect(self, '127.0.0.1', port, 4);
588620
}
589621
return self;
590622
};
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
var common = require('../common');
23+
var assert = require('assert');
24+
var net = require('net');
25+
26+
var serverGotEnd = false;
27+
var clientGotEnd = false;
28+
29+
var server = net.createServer({allowHalfOpen: true}, function(socket) {
30+
socket.on('end', function() {
31+
serverGotEnd = true;
32+
});
33+
socket.end();
34+
});
35+
36+
server.listen(common.PORT, function() {
37+
var client = net.connect({
38+
host: '127.0.0.1',
39+
port: common.PORT,
40+
allowHalfOpen: true
41+
}, function() {
42+
client.on('end', function() {
43+
clientGotEnd = true;
44+
setTimeout(function() {
45+
assert(client.writable);
46+
client.end();
47+
}, 10);
48+
});
49+
client.on('close', function() {
50+
server.close();
51+
});
52+
});
53+
});
54+
55+
process.on('exit', function() {
56+
assert(serverGotEnd);
57+
assert(clientGotEnd);
58+
});

0 commit comments

Comments
 (0)