Skip to content

Commit 8fd61e1

Browse files
AndreasMadsengibfahn
authored andcommitted
async_wrap: add provider types for net server
Adds `TCPSERVERWRAP` and `PIPESERVERWRAP` as provider types. This makes it possible to distinguish servers from connections. PR-URL: #17157 Backport-PR-URL: #17623 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent 673e263 commit 8fd61e1

32 files changed

+289
-169
lines changed

benchmark/net/tcp-raw-c2s.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const bench = common.createBenchmark(main, {
1414
dur: [5]
1515
});
1616

17-
const TCP = process.binding('tcp_wrap').TCP;
17+
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
1818
const TCPConnectWrap = process.binding('tcp_wrap').TCPConnectWrap;
1919
const WriteWrap = process.binding('stream_wrap').WriteWrap;
2020
const PORT = common.PORT;
@@ -36,7 +36,7 @@ function fail(err, syscall) {
3636
}
3737

3838
function server() {
39-
const serverHandle = new TCP();
39+
const serverHandle = new TCP(TCPConstants.SERVER);
4040
var err = serverHandle.bind('127.0.0.1', PORT);
4141
if (err)
4242
fail(err, 'bind');
@@ -92,7 +92,7 @@ function client() {
9292
throw new Error(`invalid type: ${type}`);
9393
}
9494

95-
const clientHandle = new TCP();
95+
const clientHandle = new TCP(TCPConstants.SOCKET);
9696
const connectReq = new TCPConnectWrap();
9797
const err = clientHandle.connect(connectReq, '127.0.0.1', PORT);
9898

benchmark/net/tcp-raw-pipe.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const bench = common.createBenchmark(main, {
1414
dur: [5]
1515
});
1616

17-
const TCP = process.binding('tcp_wrap').TCP;
17+
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
1818
const TCPConnectWrap = process.binding('tcp_wrap').TCPConnectWrap;
1919
const WriteWrap = process.binding('stream_wrap').WriteWrap;
2020
const PORT = common.PORT;
@@ -35,7 +35,7 @@ function fail(err, syscall) {
3535
}
3636

3737
function server() {
38-
const serverHandle = new TCP();
38+
const serverHandle = new TCP(TCPConstants.SERVER);
3939
var err = serverHandle.bind('127.0.0.1', PORT);
4040
if (err)
4141
fail(err, 'bind');
@@ -89,7 +89,7 @@ function client() {
8989
throw new Error(`invalid type: ${type}`);
9090
}
9191

92-
const clientHandle = new TCP();
92+
const clientHandle = new TCP(TCPConstants.SOCKET);
9393
const connectReq = new TCPConnectWrap();
9494
const err = clientHandle.connect(connectReq, '127.0.0.1', PORT);
9595
var bytes = 0;

benchmark/net/tcp-raw-s2c.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const bench = common.createBenchmark(main, {
1414
dur: [5]
1515
});
1616

17-
const TCP = process.binding('tcp_wrap').TCP;
17+
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
1818
const TCPConnectWrap = process.binding('tcp_wrap').TCPConnectWrap;
1919
const WriteWrap = process.binding('stream_wrap').WriteWrap;
2020
const PORT = common.PORT;
@@ -35,7 +35,7 @@ function fail(err, syscall) {
3535
}
3636

3737
function server() {
38-
const serverHandle = new TCP();
38+
const serverHandle = new TCP(TCPConstants.SERVER);
3939
var err = serverHandle.bind('127.0.0.1', PORT);
4040
if (err)
4141
fail(err, 'bind');
@@ -107,7 +107,7 @@ function server() {
107107
}
108108

109109
function client() {
110-
const clientHandle = new TCP();
110+
const clientHandle = new TCP(TCPConstants.SOCKET);
111111
const connectReq = new TCPConnectWrap();
112112
const err = clientHandle.connect(connectReq, '127.0.0.1', PORT);
113113

doc/api/async_hooks.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ resource's constructor.
234234
```text
235235
FSEVENTWRAP, FSREQWRAP, GETADDRINFOREQWRAP, GETNAMEINFOREQWRAP, HTTPPARSER,
236236
JSSTREAM, PIPECONNECTWRAP, PIPEWRAP, PROCESSWRAP, QUERYWRAP, SHUTDOWNWRAP,
237-
SIGNALWRAP, STATWATCHER, TCPCONNECTWRAP, TCPWRAP, TIMERWRAP, TTYWRAP,
237+
SIGNALWRAP, STATWATCHER, TCPCONNECTWRAP, TCPSERVER, TCPWRAP, TIMERWRAP, TTYWRAP,
238238
UDPSENDWRAP, UDPWRAP, WRITEWRAP, ZLIB, SSLCONNECTION, PBKDF2REQUEST,
239239
RANDOMBYTESREQUEST, TLSWRAP, Timeout, Immediate, TickObject
240240
```
@@ -273,13 +273,13 @@ require('net').createServer((conn) => {}).listen(8080);
273273
Output when hitting the server with `nc localhost 8080`:
274274

275275
```console
276-
TCPWRAP(2): trigger: 1 execution: 1
276+
TCPSERVERWRAP(2): trigger: 1 execution: 1
277277
TCPWRAP(4): trigger: 2 execution: 0
278278
```
279279

280-
The first `TCPWRAP` is the server which receives the connections.
280+
The `TCPSERVERWRAP` is the server which receives the connections.
281281

282-
The second `TCPWRAP` is the new connection from the client. When a new
282+
The `TCPWRAP` is the new connection from the client. When a new
283283
connection is made the `TCPWrap` instance is immediately constructed. This
284284
happens outside of any JavaScript stack (side note: a `executionAsyncId()` of `0`
285285
means it's being executed from C++, with no JavaScript stack above it).
@@ -352,7 +352,7 @@ require('net').createServer(() => {}).listen(8080, () => {
352352
Output from only starting the server:
353353

354354
```console
355-
TCPWRAP(2): trigger: 1 execution: 1
355+
TCPSERVERWRAP(2): trigger: 1 execution: 1
356356
TickObject(3): trigger: 2 execution: 1
357357
before: 3
358358
Timeout(4): trigger: 3 execution: 3
@@ -385,7 +385,7 @@ Only using `execution` to graph resource allocation results in the following:
385385
TTYWRAP(6) -> Timeout(4) -> TIMERWRAP(5) -> TickObject(3) -> root(1)
386386
```
387387

388-
The `TCPWRAP` is not part of this graph, even though it was the reason for
388+
The `TCPSERVERWRAP` is not part of this graph, even though it was the reason for
389389
`console.log()` being called. This is because binding to a port without a
390390
hostname is a *synchronous* operation, but to maintain a completely asynchronous
391391
API the user's callback is placed in a `process.nextTick()`.

lib/_tls_wrap.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ const { Buffer } = require('buffer');
3434
const debug = util.debuglog('tls');
3535
const { Timer } = process.binding('timer_wrap');
3636
const tls_wrap = process.binding('tls_wrap');
37-
const { TCP } = process.binding('tcp_wrap');
38-
const { Pipe } = process.binding('pipe_wrap');
37+
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
38+
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
3939
const kDisableRenegotiation = Symbol('disable-renegotiation');
4040

4141
function onhandshakestart() {
@@ -376,7 +376,9 @@ TLSSocket.prototype._wrapHandle = function(wrap) {
376376

377377
var options = this._tlsOptions;
378378
if (!handle) {
379-
handle = options.pipe ? new Pipe() : new TCP();
379+
handle = options.pipe ?
380+
new Pipe(PipeConstants.SOCKET) :
381+
new TCP(TCPConstants.SOCKET);
380382
handle.owner = this;
381383
}
382384

lib/child_process.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const debug = util.debuglog('child_process');
3131
const uv = process.binding('uv');
3232
const spawn_sync = process.binding('spawn_sync');
3333
const { Buffer } = require('buffer');
34-
const { Pipe } = process.binding('pipe_wrap');
34+
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
3535
const child_process = require('internal/child_process');
3636
const {
3737
_validateStdio,
@@ -106,7 +106,7 @@ exports.fork = function(modulePath /*, args, options*/) {
106106

107107
exports._forkChild = function(fd) {
108108
// set process.send()
109-
var p = new Pipe(true);
109+
var p = new Pipe(PipeConstants.IPC);
110110
p.open(fd);
111111
p.unref();
112112
const control = setupChannel(process, p);

lib/internal/child_process.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const assert = require('assert');
1010
const uv = process.binding('uv');
1111
const { Process } = process.binding('process_wrap');
1212
const { WriteWrap } = process.binding('stream_wrap');
13-
const { Pipe } = process.binding('pipe_wrap');
13+
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
1414
const { TTY } = process.binding('tty_wrap');
1515
const { TCP } = process.binding('tcp_wrap');
1616
const { UDP } = process.binding('udp_wrap');
@@ -845,7 +845,7 @@ function _validateStdio(stdio, sync) {
845845
};
846846

847847
if (!sync)
848-
a.handle = new Pipe();
848+
a.handle = new Pipe(PipeConstants.SOCKET);
849849

850850
acc.push(a);
851851
} else if (stdio === 'ipc') {
@@ -858,7 +858,7 @@ function _validateStdio(stdio, sync) {
858858
throw new errors.Error('ERR_IPC_SYNC_FORK');
859859
}
860860

861-
ipc = new Pipe(true);
861+
ipc = new Pipe(PipeConstants.IPC);
862862
ipcFd = i;
863863

864864
acc.push({

lib/net.js

+23-11
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ const uv = process.binding('uv');
3333

3434
const { Buffer } = require('buffer');
3535
const TTYWrap = process.binding('tty_wrap');
36-
const { TCP } = process.binding('tcp_wrap');
37-
const { Pipe } = process.binding('pipe_wrap');
36+
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
37+
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
3838
const { TCPConnectWrap } = process.binding('tcp_wrap');
3939
const { PipeConnectWrap } = process.binding('pipe_wrap');
4040
const { ShutdownWrap, WriteWrap } = process.binding('stream_wrap');
@@ -53,10 +53,20 @@ const exceptionWithHostPort = util._exceptionWithHostPort;
5353

5454
function noop() {}
5555

56-
function createHandle(fd) {
57-
var type = TTYWrap.guessHandleType(fd);
58-
if (type === 'PIPE') return new Pipe();
59-
if (type === 'TCP') return new TCP();
56+
function createHandle(fd, is_server) {
57+
const type = TTYWrap.guessHandleType(fd);
58+
if (type === 'PIPE') {
59+
return new Pipe(
60+
is_server ? PipeConstants.SERVER : PipeConstants.SOCKET
61+
);
62+
}
63+
64+
if (type === 'TCP') {
65+
return new TCP(
66+
is_server ? TCPConstants.SERVER : TCPConstants.SOCKET
67+
);
68+
}
69+
6070
throw new TypeError('Unsupported fd type: ' + type);
6171
}
6272

@@ -196,7 +206,7 @@ function Socket(options) {
196206
this._handle = options.handle; // private
197207
this[async_id_symbol] = getNewAsyncId(this._handle);
198208
} else if (options.fd !== undefined) {
199-
this._handle = createHandle(options.fd);
209+
this._handle = createHandle(options.fd, false);
200210
this._handle.open(options.fd);
201211
this[async_id_symbol] = this._handle.getAsyncId();
202212
// options.fd can be string (since it is user-defined),
@@ -1003,7 +1013,9 @@ Socket.prototype.connect = function(...args) {
10031013
debug('pipe', pipe, path);
10041014

10051015
if (!this._handle) {
1006-
this._handle = pipe ? new Pipe() : new TCP();
1016+
this._handle = pipe ?
1017+
new Pipe(PipeConstants.SOCKET) :
1018+
new TCP(TCPConstants.SOCKET);
10071019
initSocketHandle(this);
10081020
}
10091021

@@ -1253,7 +1265,7 @@ function createServerHandle(address, port, addressType, fd) {
12531265
var isTCP = false;
12541266
if (typeof fd === 'number' && fd >= 0) {
12551267
try {
1256-
handle = createHandle(fd);
1268+
handle = createHandle(fd, true);
12571269
} catch (e) {
12581270
// Not a fd we can listen on. This will trigger an error.
12591271
debug('listen invalid fd=%d:', fd, e.message);
@@ -1264,15 +1276,15 @@ function createServerHandle(address, port, addressType, fd) {
12641276
handle.writable = true;
12651277
assert(!address && !port);
12661278
} else if (port === -1 && addressType === -1) {
1267-
handle = new Pipe();
1279+
handle = new Pipe(PipeConstants.SERVER);
12681280
if (process.platform === 'win32') {
12691281
var instances = parseInt(process.env.NODE_PENDING_PIPE_INSTANCES);
12701282
if (!isNaN(instances)) {
12711283
handle.setPendingInstances(instances);
12721284
}
12731285
}
12741286
} else {
1275-
handle = new TCP();
1287+
handle = new TCP(TCPConstants.SERVER);
12761288
isTCP = true;
12771289
}
12781290

src/async-wrap.h

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ namespace node {
4747
V(HTTPPARSER) \
4848
V(JSSTREAM) \
4949
V(PIPECONNECTWRAP) \
50+
V(PIPESERVERWRAP) \
5051
V(PIPEWRAP) \
5152
V(PROCESSWRAP) \
5253
V(PROMISE) \
@@ -55,6 +56,7 @@ namespace node {
5556
V(SIGNALWRAP) \
5657
V(STATWATCHER) \
5758
V(TCPCONNECTWRAP) \
59+
V(TCPSERVERWRAP) \
5860
V(TCPWRAP) \
5961
V(TIMERWRAP) \
6062
V(TTYWRAP) \

src/connection_wrap.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ void ConnectionWrap<WrapType, UVType>::OnConnection(uv_stream_t* handle,
5151
if (status == 0) {
5252
env->set_init_trigger_async_id(wrap_data->get_async_id());
5353
// Instantiate the client javascript object and handle.
54-
Local<Object> client_obj = WrapType::Instantiate(env, wrap_data);
54+
Local<Object> client_obj = WrapType::Instantiate(env,
55+
wrap_data,
56+
WrapType::SOCKET);
5557

5658
// Unwrap the client javascript object.
5759
WrapType* wrap;

src/pipe_wrap.cc

+42-6
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ using v8::Function;
3939
using v8::FunctionCallbackInfo;
4040
using v8::FunctionTemplate;
4141
using v8::HandleScope;
42+
using v8::Int32;
4243
using v8::Local;
4344
using v8::Object;
4445
using v8::String;
@@ -47,14 +48,17 @@ using v8::Value;
4748
using AsyncHooks = Environment::AsyncHooks;
4849

4950

50-
Local<Object> PipeWrap::Instantiate(Environment* env, AsyncWrap* parent) {
51+
Local<Object> PipeWrap::Instantiate(Environment* env,
52+
AsyncWrap* parent,
53+
PipeWrap::SocketType type) {
5154
EscapableHandleScope handle_scope(env->isolate());
5255
AsyncHooks::InitScope init_scope(env, parent->get_async_id());
5356
CHECK_EQ(false, env->pipe_constructor_template().IsEmpty());
5457
Local<Function> constructor = env->pipe_constructor_template()->GetFunction();
5558
CHECK_EQ(false, constructor.IsEmpty());
59+
Local<Value> type_value = Int32::New(env->isolate(), type);
5660
Local<Object> instance =
57-
constructor->NewInstance(env->context()).ToLocalChecked();
61+
constructor->NewInstance(env->context(), 1, &type_value).ToLocalChecked();
5862
return handle_scope.Escape(instance);
5963
}
6064

@@ -106,6 +110,15 @@ void PipeWrap::Initialize(Local<Object> target,
106110
FIXED_ONE_BYTE_STRING(env->isolate(), "PipeConnectWrap");
107111
cwt->SetClassName(wrapString);
108112
target->Set(wrapString, cwt->GetFunction());
113+
114+
// Define constants
115+
Local<Object> constants = Object::New(env->isolate());
116+
NODE_DEFINE_CONSTANT(constants, SOCKET);
117+
NODE_DEFINE_CONSTANT(constants, SERVER);
118+
NODE_DEFINE_CONSTANT(constants, IPC);
119+
target->Set(context,
120+
FIXED_ONE_BYTE_STRING(env->isolate(), "constants"),
121+
constants).FromJust();
109122
}
110123

111124

@@ -114,17 +127,40 @@ void PipeWrap::New(const FunctionCallbackInfo<Value>& args) {
114127
// Therefore we assert that we are not trying to call this as a
115128
// normal function.
116129
CHECK(args.IsConstructCall());
130+
CHECK(args[0]->IsInt32());
117131
Environment* env = Environment::GetCurrent(args);
118-
new PipeWrap(env, args.This(), args[0]->IsTrue());
132+
133+
int type_value = args[0].As<Int32>()->Value();
134+
PipeWrap::SocketType type = static_cast<PipeWrap::SocketType>(type_value);
135+
136+
bool ipc;
137+
ProviderType provider;
138+
switch (type) {
139+
case SOCKET:
140+
provider = PROVIDER_PIPEWRAP;
141+
ipc = false;
142+
break;
143+
case SERVER:
144+
provider = PROVIDER_PIPESERVERWRAP;
145+
ipc = false;
146+
break;
147+
case IPC:
148+
provider = PROVIDER_PIPEWRAP;
149+
ipc = true;
150+
break;
151+
default:
152+
UNREACHABLE();
153+
}
154+
155+
new PipeWrap(env, args.This(), provider, ipc);
119156
}
120157

121158

122159
PipeWrap::PipeWrap(Environment* env,
123160
Local<Object> object,
161+
ProviderType provider,
124162
bool ipc)
125-
: ConnectionWrap(env,
126-
object,
127-
AsyncWrap::PROVIDER_PIPEWRAP) {
163+
: ConnectionWrap(env, object, provider) {
128164
int r = uv_pipe_init(env->event_loop(), &handle_, ipc);
129165
CHECK_EQ(r, 0); // How do we proxy this error up to javascript?
130166
// Suggestion: uv_pipe_init() returns void.

0 commit comments

Comments
 (0)