Skip to content

Commit f337595

Browse files
committed
lib,src: add unix socket getsockname/getpeername
The implementation is a minor API change in that socket.address() now returns a `{ address: '/path/to/socket' }` object, like it does for TCP and UDP sockets. Before this commit, it returned `socket._pipeName`, which is a string when present. Change common.PIPE on Windows from '\\\\.\\pipe\\libuv-test' to '\\\\?\\pipe\\libuv-test'. Windows converts the '.' to a '?' when creating a named pipe, meaning that common.PIPE didn't match the result from NtQueryInformationFile(). Fixes: #954 PR-URL: #956 Reviewed-By: Sam Roberts <vieuxtech@gmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
1 parent a43af39 commit f337595

8 files changed

+56
-15
lines changed

doc/api/net.markdown

+15-5
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,9 @@ Example:
255255

256256
Don't call `server.address()` until the `'listening'` event has been emitted.
257257

258+
This method used to return the file path as a string for UNIX sockets and
259+
Windows pipes. As of io.js v1.5.0, it returns the expected object.
260+
258261
### server.unref()
259262

260263
Calling `unref` on a server will allow the program to exit if this is the only
@@ -508,25 +511,32 @@ Returns `socket`.
508511
The string representation of the remote IP address. For example,
509512
`'74.125.127.100'` or `'2001:4860:a005::68'`.
510513

514+
For UNIX sockets and Windows pipes, the file path the socket is connected
515+
to. The remote address for server sockets is always `''`, the empty string.
516+
511517
### socket.remoteFamily
512518

513-
The string representation of the remote IP family. `'IPv4'` or `'IPv6'`.
519+
The string representation of the remote IP family. `'IPv4'` or `'IPv6'`
520+
for TCP sockets, `'pipe'` for UNIX sockets and Windows pipes.
514521

515522
### socket.remotePort
516523

517-
The numeric representation of the remote port. For example,
518-
`80` or `21`.
524+
The numeric representation of the remote port. For example, `80` or `21`.
525+
`undefined` for UNIX sockets and Windows pipes.
519526

520527
### socket.localAddress
521528

522529
The string representation of the local IP address the remote client is
523530
connecting on. For example, if you are listening on `'0.0.0.0'` and the
524531
client connects on `'192.168.1.1'`, the value would be `'192.168.1.1'`.
525532

533+
For UNIX sockets and Windows pipes, the file path the socket is listening
534+
on. The local address for client sockets is always `''`, the empty string.
535+
526536
### socket.localPort
527537

528-
The numeric representation of the local port. For example,
529-
`80` or `21`.
538+
The numeric representation of the local port. For example, `80` or `21`.
539+
`undefined` for UNIX sockets and Windows pipes.
530540

531541
### socket.bytesRead
532542

lib/net.js

+2-6
Original file line numberDiff line numberDiff line change
@@ -1339,16 +1339,14 @@ Server.prototype.listen = function() {
13391339
else
13401340
listen(self, null, h.port | 0, 4, backlog, undefined, h.exclusive);
13411341
} else if (h.path && isPipeName(h.path)) {
1342-
var pipeName = self._pipeName = h.path;
1343-
listen(self, pipeName, -1, -1, backlog, undefined, h.exclusive);
1342+
listen(self, h.path, -1, -1, backlog, undefined, h.exclusive);
13441343
} else {
13451344
throw new Error('Invalid listen argument: ' + h);
13461345
}
13471346
}
13481347
} else if (isPipeName(arguments[0])) {
13491348
// UNIX socket or Windows pipe.
1350-
var pipeName = self._pipeName = arguments[0];
1351-
listen(self, pipeName, -1, -1, backlog);
1349+
listen(self, arguments[0], -1, -1, backlog);
13521350

13531351
} else if (arguments[1] === undefined ||
13541352
typeof arguments[1] === 'function' ||
@@ -1381,8 +1379,6 @@ Server.prototype.address = function() {
13811379
this._handle.getsockname(out);
13821380
// TODO(bnoordhuis) Check err and throw?
13831381
return out;
1384-
} else if (this._pipeName) {
1385-
return this._pipeName;
13861382
} else {
13871383
return null;
13881384
}

src/pipe_wrap.cc

+26
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ void PipeWrap::Initialize(Handle<Object> target,
8989
env->SetProtoMethod(t, "listen", Listen);
9090
env->SetProtoMethod(t, "connect", Connect);
9191
env->SetProtoMethod(t, "open", Open);
92+
env->SetProtoMethod(t, "getpeername",
93+
GetSockOrPeerName<uv_pipe_getpeername>);
94+
env->SetProtoMethod(t, "getsockname",
95+
GetSockOrPeerName<uv_pipe_getsockname>);
9296

9397
#ifdef _WIN32
9498
env->SetProtoMethod(t, "setPendingInstances", SetPendingInstances);
@@ -276,6 +280,28 @@ void PipeWrap::Connect(const FunctionCallbackInfo<Value>& args) {
276280
}
277281

278282

283+
template <int (*F)(const uv_pipe_t*, char*, size_t*)>
284+
void PipeWrap::GetSockOrPeerName(
285+
const v8::FunctionCallbackInfo<v8::Value>& args) {
286+
CHECK(args[0]->IsObject());
287+
char buffer[1024];
288+
size_t size = sizeof(buffer);
289+
const PipeWrap* wrap = Unwrap<PipeWrap>(args.Holder());
290+
const int err = F(&wrap->handle_, buffer, &size);
291+
if (err == 0) {
292+
const uint8_t* data = reinterpret_cast<const uint8_t*>(buffer);
293+
const String::NewStringType type = String::kNormalString;
294+
Local<String> path =
295+
String::NewFromOneByte(args.GetIsolate(), data, type, size);
296+
Environment* env = Environment::GetCurrent(args);
297+
Local<Object> out = args[0].As<Object>();
298+
out->Set(env->address_string(), path);
299+
out->Set(env->family_string(), env->pipe_string());
300+
}
301+
args.GetReturnValue().Set(err);
302+
}
303+
304+
279305
} // namespace node
280306

281307
NODE_MODULE_CONTEXT_AWARE_BUILTIN(pipe_wrap, node::PipeWrap::Initialize)

src/pipe_wrap.h

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ class PipeWrap : public StreamWrap {
3030
static void Connect(const v8::FunctionCallbackInfo<v8::Value>& args);
3131
static void Open(const v8::FunctionCallbackInfo<v8::Value>& args);
3232

33+
template <int (*F)(const uv_pipe_t*, char*, size_t*)>
34+
static void GetSockOrPeerName(const v8::FunctionCallbackInfo<v8::Value>&);
35+
3336
#ifdef _WIN32
3437
static void SetPendingInstances(
3538
const v8::FunctionCallbackInfo<v8::Value>& args);

test/common.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ Object.defineProperty(exports, 'hasCrypto', {get: function() {
134134
}});
135135

136136
if (exports.isWindows) {
137-
exports.PIPE = '\\\\.\\pipe\\libuv-test';
137+
exports.PIPE = '\\\\?\\pipe\\libuv-test';
138138
} else {
139139
exports.PIPE = exports.tmpDir + '/test.sock';
140140
}

test/parallel/test-cluster-http-pipe.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@ if (cluster.isMaster) {
2929
}
3030

3131
http.createServer(function(req, res) {
32-
assert.equal(req.connection.remoteAddress, undefined);
33-
assert.equal(req.connection.localAddress, undefined); // TODO common.PIPE?
32+
assert.equal(req.connection.remoteAddress, '');
33+
assert.equal(req.connection.remoteFamily, 'pipe');
34+
assert.equal(req.connection.remotePort, undefined);
35+
assert.equal(req.connection.localAddress, common.PIPE);
36+
assert.equal(req.connection.localPort, undefined);
3437
res.writeHead(200);
3538
res.end('OK');
3639
}).listen(common.PIPE, function() {

test/parallel/test-http-unix-socket.js

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ var headers_ok = false;
99
var body_ok = false;
1010

1111
var server = http.createServer(function(req, res) {
12+
assert.equal(req.socket.address().address, common.PIPE);
1213
res.writeHead(200, {
1314
'Content-Type': 'text/plain',
1415
'Connection': 'close'
@@ -19,6 +20,7 @@ var server = http.createServer(function(req, res) {
1920
});
2021

2122
server.listen(common.PIPE, function() {
23+
assert.equal(server.address().address, common.PIPE);
2224

2325
var options = {
2426
socketPath: common.PIPE,

test/sequential/test-pipe-address.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ server.listen(common.PIPE, function() {
1515
});
1616

1717
process.on('exit', function() {
18-
assert.equal(address, common.PIPE);
18+
assert.equal(address.address, common.PIPE);
19+
assert.equal(address.family, 'pipe');
1920
});

0 commit comments

Comments
 (0)