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: https://github.com/nodejs/node/pull/17157
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
Andreas Madsen 2017-11-20 17:18:40 +01:00 коммит произвёл Anna Henningsen
Родитель 91d131210c
Коммит b44efded84
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 9C63F3A6CD2AD8F9
32 изменённых файлов: 286 добавлений и 168 удалений

Просмотреть файл

@ -14,7 +14,7 @@ const bench = common.createBenchmark(main, {
dur: [5]
});
const TCP = process.binding('tcp_wrap').TCP;
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
const TCPConnectWrap = process.binding('tcp_wrap').TCPConnectWrap;
const WriteWrap = process.binding('stream_wrap').WriteWrap;
const PORT = common.PORT;
@ -36,7 +36,7 @@ function fail(err, syscall) {
}
function server() {
const serverHandle = new TCP();
const serverHandle = new TCP(TCPConstants.SERVER);
var err = serverHandle.bind('127.0.0.1', PORT);
if (err)
fail(err, 'bind');
@ -92,7 +92,7 @@ function client() {
throw new Error(`invalid type: ${type}`);
}
const clientHandle = new TCP();
const clientHandle = new TCP(TCPConstants.SOCKET);
const connectReq = new TCPConnectWrap();
const err = clientHandle.connect(connectReq, '127.0.0.1', PORT);

Просмотреть файл

@ -14,7 +14,7 @@ const bench = common.createBenchmark(main, {
dur: [5]
});
const TCP = process.binding('tcp_wrap').TCP;
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
const TCPConnectWrap = process.binding('tcp_wrap').TCPConnectWrap;
const WriteWrap = process.binding('stream_wrap').WriteWrap;
const PORT = common.PORT;
@ -35,7 +35,7 @@ function fail(err, syscall) {
}
function server() {
const serverHandle = new TCP();
const serverHandle = new TCP(TCPConstants.SERVER);
var err = serverHandle.bind('127.0.0.1', PORT);
if (err)
fail(err, 'bind');
@ -89,7 +89,7 @@ function client() {
throw new Error(`invalid type: ${type}`);
}
const clientHandle = new TCP();
const clientHandle = new TCP(TCPConstants.SOCKET);
const connectReq = new TCPConnectWrap();
const err = clientHandle.connect(connectReq, '127.0.0.1', PORT);
var bytes = 0;

Просмотреть файл

@ -14,7 +14,7 @@ const bench = common.createBenchmark(main, {
dur: [5]
});
const TCP = process.binding('tcp_wrap').TCP;
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
const TCPConnectWrap = process.binding('tcp_wrap').TCPConnectWrap;
const WriteWrap = process.binding('stream_wrap').WriteWrap;
const PORT = common.PORT;
@ -35,7 +35,7 @@ function fail(err, syscall) {
}
function server() {
const serverHandle = new TCP();
const serverHandle = new TCP(TCPConstants.SERVER);
var err = serverHandle.bind('127.0.0.1', PORT);
if (err)
fail(err, 'bind');
@ -107,7 +107,7 @@ function server() {
}
function client() {
const clientHandle = new TCP();
const clientHandle = new TCP(TCPConstants.SOCKET);
const connectReq = new TCPConnectWrap();
const err = clientHandle.connect(connectReq, '127.0.0.1', PORT);

Просмотреть файл

@ -236,7 +236,7 @@ resource's constructor.
```text
FSEVENTWRAP, FSREQWRAP, GETADDRINFOREQWRAP, GETNAMEINFOREQWRAP, HTTPPARSER,
JSSTREAM, PIPECONNECTWRAP, PIPEWRAP, PROCESSWRAP, QUERYWRAP, SHUTDOWNWRAP,
SIGNALWRAP, STATWATCHER, TCPCONNECTWRAP, TCPWRAP, TIMERWRAP, TTYWRAP,
SIGNALWRAP, STATWATCHER, TCPCONNECTWRAP, TCPSERVER, TCPWRAP, TIMERWRAP, TTYWRAP,
UDPSENDWRAP, UDPWRAP, WRITEWRAP, ZLIB, SSLCONNECTION, PBKDF2REQUEST,
RANDOMBYTESREQUEST, TLSWRAP, Timeout, Immediate, TickObject
```
@ -275,13 +275,13 @@ require('net').createServer((conn) => {}).listen(8080);
Output when hitting the server with `nc localhost 8080`:
```console
TCPWRAP(2): trigger: 1 execution: 1
TCPSERVERWRAP(2): trigger: 1 execution: 1
TCPWRAP(4): trigger: 2 execution: 0
```
The first `TCPWRAP` is the server which receives the connections.
The `TCPSERVERWRAP` is the server which receives the connections.
The second `TCPWRAP` is the new connection from the client. When a new
The `TCPWRAP` is the new connection from the client. When a new
connection is made the `TCPWrap` instance is immediately constructed. This
happens outside of any JavaScript stack (side note: a `executionAsyncId()` of `0`
means it's being executed from C++, with no JavaScript stack above it).
@ -354,7 +354,7 @@ require('net').createServer(() => {}).listen(8080, () => {
Output from only starting the server:
```console
TCPWRAP(2): trigger: 1 execution: 1
TCPSERVERWRAP(2): trigger: 1 execution: 1
TickObject(3): trigger: 2 execution: 1
before: 3
Timeout(4): trigger: 3 execution: 3
@ -387,7 +387,7 @@ Only using `execution` to graph resource allocation results in the following:
TTYWRAP(6) -> Timeout(4) -> TIMERWRAP(5) -> TickObject(3) -> root(1)
```
The `TCPWRAP` is not part of this graph, even though it was the reason for
The `TCPSERVERWRAP` is not part of this graph, even though it was the reason for
`console.log()` being called. This is because binding to a port without a
hostname is a *synchronous* operation, but to maintain a completely asynchronous
API the user's callback is placed in a `process.nextTick()`.

Просмотреть файл

@ -34,8 +34,8 @@ const { Buffer } = require('buffer');
const debug = util.debuglog('tls');
const { Timer } = process.binding('timer_wrap');
const tls_wrap = process.binding('tls_wrap');
const { TCP } = process.binding('tcp_wrap');
const { Pipe } = process.binding('pipe_wrap');
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
const errors = require('internal/errors');
const kConnectOptions = Symbol('connect-options');
const kDisableRenegotiation = Symbol('disable-renegotiation');
@ -398,7 +398,9 @@ TLSSocket.prototype._wrapHandle = function(wrap) {
var options = this._tlsOptions;
if (!handle) {
handle = options.pipe ? new Pipe() : new TCP();
handle = options.pipe ?
new Pipe(PipeConstants.SOCKET) :
new TCP(TCPConstants.SOCKET);
handle.owner = this;
}

Просмотреть файл

@ -28,7 +28,7 @@ const { createPromise,
promiseResolve, promiseReject } = process.binding('util');
const debug = util.debuglog('child_process');
const { Buffer } = require('buffer');
const { Pipe } = process.binding('pipe_wrap');
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
const { errname } = process.binding('uv');
const child_process = require('internal/child_process');
const {
@ -103,7 +103,7 @@ exports.fork = function(modulePath /*, args, options*/) {
exports._forkChild = function(fd) {
// set process.send()
var p = new Pipe(true);
var p = new Pipe(PipeConstants.IPC);
p.open(fd);
p.unref();
const control = setupChannel(process, p);

Просмотреть файл

@ -10,7 +10,7 @@ const assert = require('assert');
const { Process } = process.binding('process_wrap');
const { WriteWrap } = process.binding('stream_wrap');
const { Pipe } = process.binding('pipe_wrap');
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
const { TTY } = process.binding('tty_wrap');
const { TCP } = process.binding('tcp_wrap');
const { UDP } = process.binding('udp_wrap');
@ -863,7 +863,7 @@ function _validateStdio(stdio, sync) {
};
if (!sync)
a.handle = new Pipe();
a.handle = new Pipe(PipeConstants.SOCKET);
acc.push(a);
} else if (stdio === 'ipc') {
@ -876,7 +876,7 @@ function _validateStdio(stdio, sync) {
throw new errors.Error('ERR_IPC_SYNC_FORK');
}
ipc = new Pipe(true);
ipc = new Pipe(PipeConstants.IPC);
ipcFd = i;
acc.push({

Просмотреть файл

@ -37,8 +37,8 @@ const {
const { Buffer } = require('buffer');
const TTYWrap = process.binding('tty_wrap');
const { TCP } = process.binding('tcp_wrap');
const { Pipe } = process.binding('pipe_wrap');
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
const { TCPConnectWrap } = process.binding('tcp_wrap');
const { PipeConnectWrap } = process.binding('pipe_wrap');
const { ShutdownWrap, WriteWrap } = process.binding('stream_wrap');
@ -57,10 +57,20 @@ const exceptionWithHostPort = util._exceptionWithHostPort;
function noop() {}
function createHandle(fd) {
function createHandle(fd, is_server) {
const type = TTYWrap.guessHandleType(fd);
if (type === 'PIPE') return new Pipe();
if (type === 'TCP') return new TCP();
if (type === 'PIPE') {
return new Pipe(
is_server ? PipeConstants.SERVER : PipeConstants.SOCKET
);
}
if (type === 'TCP') {
return new TCP(
is_server ? TCPConstants.SERVER : TCPConstants.SOCKET
);
}
throw new errors.TypeError('ERR_INVALID_FD_TYPE', type);
}
@ -200,7 +210,7 @@ function Socket(options) {
this._handle = options.handle; // private
this[async_id_symbol] = getNewAsyncId(this._handle);
} else if (options.fd !== undefined) {
this._handle = createHandle(options.fd);
this._handle = createHandle(options.fd, false);
this._handle.open(options.fd);
this[async_id_symbol] = this._handle.getAsyncId();
// options.fd can be string (since it is user-defined),
@ -1009,7 +1019,9 @@ Socket.prototype.connect = function(...args) {
debug('pipe', pipe, path);
if (!this._handle) {
this._handle = pipe ? new Pipe() : new TCP();
this._handle = pipe ?
new Pipe(PipeConstants.SOCKET) :
new TCP(TCPConstants.SOCKET);
initSocketHandle(this);
}
@ -1269,7 +1281,7 @@ function createServerHandle(address, port, addressType, fd) {
var isTCP = false;
if (typeof fd === 'number' && fd >= 0) {
try {
handle = createHandle(fd);
handle = createHandle(fd, true);
} catch (e) {
// Not a fd we can listen on. This will trigger an error.
debug('listen invalid fd=%d:', fd, e.message);
@ -1280,7 +1292,7 @@ function createServerHandle(address, port, addressType, fd) {
handle.writable = true;
assert(!address && !port);
} else if (port === -1 && addressType === -1) {
handle = new Pipe();
handle = new Pipe(PipeConstants.SERVER);
if (process.platform === 'win32') {
var instances = parseInt(process.env.NODE_PENDING_PIPE_INSTANCES);
if (!isNaN(instances)) {
@ -1288,7 +1300,7 @@ function createServerHandle(address, port, addressType, fd) {
}
}
} else {
handle = new TCP();
handle = new TCP(TCPConstants.SERVER);
isTCP = true;
}

Просмотреть файл

@ -46,6 +46,7 @@ namespace node {
V(HTTPPARSER) \
V(JSSTREAM) \
V(PIPECONNECTWRAP) \
V(PIPESERVERWRAP) \
V(PIPEWRAP) \
V(PROCESSWRAP) \
V(PROMISE) \
@ -54,6 +55,7 @@ namespace node {
V(SIGNALWRAP) \
V(STATWATCHER) \
V(TCPCONNECTWRAP) \
V(TCPSERVERWRAP) \
V(TCPWRAP) \
V(TIMERWRAP) \
V(TTYWRAP) \

Просмотреть файл

@ -51,7 +51,9 @@ void ConnectionWrap<WrapType, UVType>::OnConnection(uv_stream_t* handle,
if (status == 0) {
env->set_init_trigger_async_id(wrap_data->get_async_id());
// Instantiate the client javascript object and handle.
Local<Object> client_obj = WrapType::Instantiate(env, wrap_data);
Local<Object> client_obj = WrapType::Instantiate(env,
wrap_data,
WrapType::SOCKET);
// Unwrap the client javascript object.
WrapType* wrap;

Просмотреть файл

@ -40,6 +40,7 @@ using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::HandleScope;
using v8::Int32;
using v8::Local;
using v8::Object;
using v8::String;
@ -48,14 +49,17 @@ using v8::Value;
using AsyncHooks = Environment::AsyncHooks;
Local<Object> PipeWrap::Instantiate(Environment* env, AsyncWrap* parent) {
Local<Object> PipeWrap::Instantiate(Environment* env,
AsyncWrap* parent,
PipeWrap::SocketType type) {
EscapableHandleScope handle_scope(env->isolate());
AsyncHooks::InitScope init_scope(env, parent->get_async_id());
CHECK_EQ(false, env->pipe_constructor_template().IsEmpty());
Local<Function> constructor = env->pipe_constructor_template()->GetFunction();
CHECK_EQ(false, constructor.IsEmpty());
Local<Value> type_value = Int32::New(env->isolate(), type);
Local<Object> instance =
constructor->NewInstance(env->context()).ToLocalChecked();
constructor->NewInstance(env->context(), 1, &type_value).ToLocalChecked();
return handle_scope.Escape(instance);
}
@ -107,6 +111,15 @@ void PipeWrap::Initialize(Local<Object> target,
FIXED_ONE_BYTE_STRING(env->isolate(), "PipeConnectWrap");
cwt->SetClassName(wrapString);
target->Set(wrapString, cwt->GetFunction());
// Define constants
Local<Object> constants = Object::New(env->isolate());
NODE_DEFINE_CONSTANT(constants, SOCKET);
NODE_DEFINE_CONSTANT(constants, SERVER);
NODE_DEFINE_CONSTANT(constants, IPC);
target->Set(context,
FIXED_ONE_BYTE_STRING(env->isolate(), "constants"),
constants).FromJust();
}
@ -115,17 +128,40 @@ void PipeWrap::New(const FunctionCallbackInfo<Value>& args) {
// Therefore we assert that we are not trying to call this as a
// normal function.
CHECK(args.IsConstructCall());
CHECK(args[0]->IsInt32());
Environment* env = Environment::GetCurrent(args);
new PipeWrap(env, args.This(), args[0]->IsTrue());
int type_value = args[0].As<Int32>()->Value();
PipeWrap::SocketType type = static_cast<PipeWrap::SocketType>(type_value);
bool ipc;
ProviderType provider;
switch (type) {
case SOCKET:
provider = PROVIDER_PIPEWRAP;
ipc = false;
break;
case SERVER:
provider = PROVIDER_PIPESERVERWRAP;
ipc = false;
break;
case IPC:
provider = PROVIDER_PIPEWRAP;
ipc = true;
break;
default:
UNREACHABLE();
}
new PipeWrap(env, args.This(), provider, ipc);
}
PipeWrap::PipeWrap(Environment* env,
Local<Object> object,
ProviderType provider,
bool ipc)
: ConnectionWrap(env,
object,
AsyncWrap::PROVIDER_PIPEWRAP) {
: ConnectionWrap(env, object, provider) {
int r = uv_pipe_init(env->event_loop(), &handle_, ipc);
CHECK_EQ(r, 0); // How do we proxy this error up to javascript?
// Suggestion: uv_pipe_init() returns void.

Просмотреть файл

@ -32,7 +32,15 @@ namespace node {
class PipeWrap : public ConnectionWrap<PipeWrap, uv_pipe_t> {
public:
static v8::Local<v8::Object> Instantiate(Environment* env, AsyncWrap* parent);
enum SocketType {
SOCKET,
SERVER,
IPC
};
static v8::Local<v8::Object> Instantiate(Environment* env,
AsyncWrap* parent,
SocketType type);
static void Initialize(v8::Local<v8::Object> target,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context);
@ -42,6 +50,7 @@ class PipeWrap : public ConnectionWrap<PipeWrap, uv_pipe_t> {
private:
PipeWrap(Environment* env,
v8::Local<v8::Object> object,
ProviderType provider,
bool ipc);
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);

Просмотреть файл

@ -187,7 +187,7 @@ static Local<Object> AcceptHandle(Environment* env, LibuvStreamWrap* parent) {
Local<Object> wrap_obj;
UVType* handle;
wrap_obj = WrapType::Instantiate(env, parent);
wrap_obj = WrapType::Instantiate(env, parent, WrapType::SOCKET);
if (wrap_obj.IsEmpty())
return Local<Object>();

Просмотреть файл

@ -42,6 +42,7 @@ using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::HandleScope;
using v8::Int32;
using v8::Integer;
using v8::Local;
using v8::Object;
@ -51,14 +52,17 @@ using v8::Value;
using AsyncHooks = Environment::AsyncHooks;
Local<Object> TCPWrap::Instantiate(Environment* env, AsyncWrap* parent) {
Local<Object> TCPWrap::Instantiate(Environment* env,
AsyncWrap* parent,
TCPWrap::SocketType type) {
EscapableHandleScope handle_scope(env->isolate());
AsyncHooks::InitScope init_scope(env, parent->get_async_id());
CHECK_EQ(env->tcp_constructor_template().IsEmpty(), false);
Local<Function> constructor = env->tcp_constructor_template()->GetFunction();
CHECK_EQ(constructor.IsEmpty(), false);
Local<Value> type_value = Int32::New(env->isolate(), type);
Local<Object> instance =
constructor->NewInstance(env->context()).ToLocalChecked();
constructor->NewInstance(env->context(), 1, &type_value).ToLocalChecked();
return handle_scope.Escape(instance);
}
@ -122,6 +126,14 @@ void TCPWrap::Initialize(Local<Object> target,
FIXED_ONE_BYTE_STRING(env->isolate(), "TCPConnectWrap");
cwt->SetClassName(wrapString);
target->Set(wrapString, cwt->GetFunction());
// Define constants
Local<Object> constants = Object::New(env->isolate());
NODE_DEFINE_CONSTANT(constants, SOCKET);
NODE_DEFINE_CONSTANT(constants, SERVER);
target->Set(context,
FIXED_ONE_BYTE_STRING(env->isolate(), "constants"),
constants).FromJust();
}
@ -130,15 +142,30 @@ void TCPWrap::New(const FunctionCallbackInfo<Value>& args) {
// Therefore we assert that we are not trying to call this as a
// normal function.
CHECK(args.IsConstructCall());
CHECK(args[0]->IsInt32());
Environment* env = Environment::GetCurrent(args);
new TCPWrap(env, args.This());
int type_value = args[0].As<Int32>()->Value();
TCPWrap::SocketType type = static_cast<TCPWrap::SocketType>(type_value);
ProviderType provider;
switch (type) {
case SOCKET:
provider = PROVIDER_TCPWRAP;
break;
case SERVER:
provider = PROVIDER_TCPSERVERWRAP;
break;
default:
UNREACHABLE();
}
new TCPWrap(env, args.This(), provider);
}
TCPWrap::TCPWrap(Environment* env, Local<Object> object)
: ConnectionWrap(env,
object,
AsyncWrap::PROVIDER_TCPWRAP) {
TCPWrap::TCPWrap(Environment* env, Local<Object> object, ProviderType provider)
: ConnectionWrap(env, object, provider) {
int r = uv_tcp_init(env->event_loop(), &handle_);
CHECK_EQ(r, 0); // How do we proxy this error up to javascript?
// Suggestion: uv_tcp_init() returns void.

Просмотреть файл

@ -32,7 +32,14 @@ namespace node {
class TCPWrap : public ConnectionWrap<TCPWrap, uv_tcp_t> {
public:
static v8::Local<v8::Object> Instantiate(Environment* env, AsyncWrap* parent);
enum SocketType {
SOCKET,
SERVER
};
static v8::Local<v8::Object> Instantiate(Environment* env,
AsyncWrap* parent,
SocketType type);
static void Initialize(v8::Local<v8::Object> target,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context);
@ -46,7 +53,8 @@ class TCPWrap : public ConnectionWrap<TCPWrap, uv_tcp_t> {
int (*F)(const typename T::HandleType*, sockaddr*, int*)>
friend void GetSockOrPeerName(const v8::FunctionCallbackInfo<v8::Value>&);
TCPWrap(Environment* env, v8::Local<v8::Object> object);
TCPWrap(Environment* env, v8::Local<v8::Object> object,
ProviderType provider);
~TCPWrap();
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);

Просмотреть файл

@ -496,7 +496,9 @@ void UDPWrap::OnRecv(uv_udp_t* handle,
}
Local<Object> UDPWrap::Instantiate(Environment* env, AsyncWrap* parent) {
Local<Object> UDPWrap::Instantiate(Environment* env,
AsyncWrap* parent,
UDPWrap::SocketType type) {
EscapableHandleScope scope(env->isolate());
AsyncHooks::InitScope init_scope(env, parent->get_async_id());
// If this assert fires then Initialize hasn't been called yet.

Просмотреть файл

@ -35,6 +35,9 @@ namespace node {
class UDPWrap: public HandleWrap {
public:
enum SocketType {
SOCKET
};
static void Initialize(v8::Local<v8::Object> target,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context);
@ -58,7 +61,9 @@ class UDPWrap: public HandleWrap {
static void SetTTL(const v8::FunctionCallbackInfo<v8::Value>& args);
static void BufferSize(const v8::FunctionCallbackInfo<v8::Value>& args);
static v8::Local<v8::Object> Instantiate(Environment* env, AsyncWrap* parent);
static v8::Local<v8::Object> Instantiate(Environment* env,
AsyncWrap* parent,
SocketType type);
uv_udp_t* UVHandle();
size_t self_size() const override { return sizeof(*this); }

Просмотреть файл

@ -28,11 +28,11 @@ function onexit() {
hooks.disable();
verifyGraph(
hooks,
[ { type: 'PIPEWRAP', id: 'pipe:1', triggerAsyncId: null },
{ type: 'PIPEWRAP', id: 'pipe:2', triggerAsyncId: 'pipe:1' },
[ { type: 'PIPESERVERWRAP', id: 'pipeserver:1', triggerAsyncId: null },
{ type: 'PIPEWRAP', id: 'pipe:1', triggerAsyncId: 'pipeserver:1' },
{ type: 'PIPECONNECTWRAP', id: 'pipeconnect:1',
triggerAsyncId: 'pipe:2' },
{ type: 'PIPEWRAP', id: 'pipe:3', triggerAsyncId: 'pipe:1' },
{ type: 'SHUTDOWNWRAP', id: 'shutdown:1', triggerAsyncId: 'pipe:3' } ]
triggerAsyncId: 'pipe:1' },
{ type: 'PIPEWRAP', id: 'pipe:2', triggerAsyncId: 'pipeserver:1' },
{ type: 'SHUTDOWNWRAP', id: 'shutdown:1', triggerAsyncId: 'pipe:2' } ]
);
}

Просмотреть файл

@ -34,13 +34,13 @@ function onexit() {
hooks.disable();
verifyGraph(
hooks,
[ { type: 'TCPWRAP', id: 'tcp:1', triggerAsyncId: null },
{ type: 'TCPWRAP', id: 'tcp:2', triggerAsyncId: 'tcp:1' },
[ { type: 'TCPSERVERWRAP', id: 'tcpserver:1', triggerAsyncId: null },
{ type: 'TCPWRAP', id: 'tcp:1', triggerAsyncId: 'tcpserver:1' },
{ type: 'GETADDRINFOREQWRAP',
id: 'getaddrinforeq:1', triggerAsyncId: 'tcp:2' },
id: 'getaddrinforeq:1', triggerAsyncId: 'tcp:1' },
{ type: 'TCPCONNECTWRAP',
id: 'tcpconnect:1', triggerAsyncId: 'tcp:2' },
{ type: 'TCPWRAP', id: 'tcp:3', triggerAsyncId: 'tcp:1' },
{ type: 'SHUTDOWNWRAP', id: 'shutdown:1', triggerAsyncId: 'tcp:3' } ]
id: 'tcpconnect:1', triggerAsyncId: 'tcp:1' },
{ type: 'TCPWRAP', id: 'tcp:2', triggerAsyncId: 'tcpserver:1' },
{ type: 'SHUTDOWNWRAP', id: 'shutdown:1', triggerAsyncId: 'tcp:2' } ]
);
}

Просмотреть файл

@ -38,11 +38,11 @@ function onexit() {
verifyGraph(
hooks,
[ { type: 'TCPWRAP', id: 'tcp:1', triggerAsyncId: null },
{ type: 'TCPWRAP', id: 'tcp:2', triggerAsyncId: null },
[ { type: 'TCPSERVERWRAP', id: 'tcpserver:1', triggerAsyncId: null },
{ type: 'TCPWRAP', id: 'tcp:1', triggerAsyncId: null },
{ type: 'TCPCONNECTWRAP',
id: 'tcpconnect:1', triggerAsyncId: 'tcp:2' },
{ type: 'TCPWRAP', id: 'tcp:3', triggerAsyncId: 'tcp:1' },
{ type: 'SHUTDOWNWRAP', id: 'shutdown:1', triggerAsyncId: 'tcp:3' } ]
id: 'tcpconnect:1', triggerAsyncId: 'tcp:1' },
{ type: 'TCPWRAP', id: 'tcp:2', triggerAsyncId: 'tcpserver:1' },
{ type: 'SHUTDOWNWRAP', id: 'shutdown:1', triggerAsyncId: 'tcp:2' } ]
);
}

Просмотреть файл

@ -55,21 +55,21 @@ function onexit() {
verifyGraph(
hooks,
[ { type: 'TCPWRAP', id: 'tcp:1', triggerAsyncId: null },
{ type: 'TCPWRAP', id: 'tcp:2', triggerAsyncId: 'tcp:1' },
{ type: 'TLSWRAP', id: 'tls:1', triggerAsyncId: 'tcp:1' },
[ { type: 'TCPSERVERWRAP', id: 'tcpserver:1', triggerAsyncId: null },
{ type: 'TCPWRAP', id: 'tcp:1', triggerAsyncId: 'tcpserver:1' },
{ type: 'TLSWRAP', id: 'tls:1', triggerAsyncId: 'tcpserver:1' },
{ type: 'GETADDRINFOREQWRAP',
id: 'getaddrinforeq:1', triggerAsyncId: 'tls:1' },
{ type: 'TCPCONNECTWRAP',
id: 'tcpconnect:1', triggerAsyncId: 'tcp:2' },
id: 'tcpconnect:1', triggerAsyncId: 'tcp:1' },
{ type: 'WRITEWRAP', id: 'write:1', triggerAsyncId: 'tcpconnect:1' },
{ type: 'TCPWRAP', id: 'tcp:3', triggerAsyncId: 'tcp:1' },
{ type: 'TLSWRAP', id: 'tls:2', triggerAsyncId: 'tcp:1' },
{ type: 'TIMERWRAP', id: 'timer:1', triggerAsyncId: 'tcp:1' },
{ type: 'TCPWRAP', id: 'tcp:2', triggerAsyncId: 'tcpserver:1' },
{ type: 'TLSWRAP', id: 'tls:2', triggerAsyncId: 'tcpserver:1' },
{ type: 'TIMERWRAP', id: 'timer:1', triggerAsyncId: 'tcpserver:1' },
{ type: 'WRITEWRAP', id: 'write:2', triggerAsyncId: null },
{ type: 'WRITEWRAP', id: 'write:3', triggerAsyncId: null },
{ type: 'WRITEWRAP', id: 'write:4', triggerAsyncId: null },
{ type: 'Immediate', id: 'immediate:1', triggerAsyncId: 'tcp:2' },
{ type: 'Immediate', id: 'immediate:2', triggerAsyncId: 'tcp:3' } ]
{ type: 'Immediate', id: 'immediate:1', triggerAsyncId: 'tcp:1' },
{ type: 'Immediate', id: 'immediate:2', triggerAsyncId: 'tcp:2' } ]
);
}

Просмотреть файл

@ -12,7 +12,8 @@ common.refreshTmpDir();
const hooks = initHooks();
hooks.enable();
let pipe1, pipe2, pipe3;
let pipe1, pipe2;
let pipeserver;
let pipeconnect;
net.createServer(common.mustCall(function(c) {
@ -22,27 +23,27 @@ net.createServer(common.mustCall(function(c) {
})).listen(common.PIPE, common.mustCall(onlisten));
function onlisten() {
let pipes = hooks.activitiesOfTypes('PIPEWRAP');
const pipeservers = hooks.activitiesOfTypes('PIPESERVERWRAP');
let pipeconnects = hooks.activitiesOfTypes('PIPECONNECTWRAP');
assert.strictEqual(pipes.length, 1);
assert.strictEqual(pipeservers.length, 1);
assert.strictEqual(pipeconnects.length, 0);
net.connect(common.PIPE,
common.mustCall(maybeOnconnect.bind(null, 'client')));
pipes = hooks.activitiesOfTypes('PIPEWRAP');
const pipes = hooks.activitiesOfTypes('PIPEWRAP');
pipeconnects = hooks.activitiesOfTypes('PIPECONNECTWRAP');
assert.strictEqual(pipes.length, 2);
assert.strictEqual(pipes.length, 1);
assert.strictEqual(pipeconnects.length, 1);
pipeserver = pipeservers[0];
pipe1 = pipes[0];
pipe2 = pipes[1];
pipeconnect = pipeconnects[0];
assert.strictEqual(pipeserver.type, 'PIPESERVERWRAP');
assert.strictEqual(pipe1.type, 'PIPEWRAP');
assert.strictEqual(pipe2.type, 'PIPEWRAP');
assert.strictEqual(pipeconnect.type, 'PIPECONNECTWRAP');
for (const a of [ pipe1, pipe2, pipeconnect ]) {
for (const a of [ pipeserver, pipe1, pipeconnect ]) {
assert.strictEqual(typeof a.uid, 'number');
assert.strictEqual(typeof a.triggerAsyncId, 'number');
checkInvocations(a, { init: 1 }, 'after net.connect');
@ -60,18 +61,18 @@ function maybeOnconnect(source) {
const pipes = hooks.activitiesOfTypes('PIPEWRAP');
const pipeconnects = hooks.activitiesOfTypes('PIPECONNECTWRAP');
assert.strictEqual(pipes.length, 3);
assert.strictEqual(pipes.length, 2);
assert.strictEqual(pipeconnects.length, 1);
pipe3 = pipes[2];
assert.strictEqual(typeof pipe3.uid, 'number');
assert.strictEqual(typeof pipe3.triggerAsyncId, 'number');
pipe2 = pipes[1];
assert.strictEqual(typeof pipe2.uid, 'number');
assert.strictEqual(typeof pipe2.triggerAsyncId, 'number');
checkInvocations(pipe1, { init: 1, before: 1, after: 1 },
'pipe1, client connected');
checkInvocations(pipe2, { init: 1 }, 'pipe2, client connected');
checkInvocations(pipeserver, { init: 1, before: 1, after: 1 },
'pipeserver, client connected');
checkInvocations(pipe1, { init: 1 }, 'pipe1, client connected');
checkInvocations(pipeconnect, { init: 1, before: 1 },
'pipeconnect, client connected');
checkInvocations(pipe3, { init: 1 }, 'pipe3, client connected');
checkInvocations(pipe2, { init: 1 }, 'pipe2, client connected');
tick(5);
}
@ -80,14 +81,15 @@ process.on('exit', onexit);
function onexit() {
hooks.disable();
hooks.sanityCheck('PIPEWRAP');
hooks.sanityCheck('PIPESERVERWRAP');
hooks.sanityCheck('PIPECONNECTWRAP');
// TODO(thlorenz) why have some of those 'before' and 'after' called twice
checkInvocations(pipe1, { init: 1, before: 1, after: 1, destroy: 1 },
checkInvocations(pipeserver, { init: 1, before: 1, after: 1, destroy: 1 },
'pipeserver, process exiting');
checkInvocations(pipe1, { init: 1, before: 2, after: 2, destroy: 1 },
'pipe1, process exiting');
checkInvocations(pipe2, { init: 1, before: 2, after: 2, destroy: 1 },
'pipe2, process exiting');
checkInvocations(pipeconnect, { init: 1, before: 1, after: 1, destroy: 1 },
'pipeconnect, process exiting');
checkInvocations(pipe3, { init: 1, before: 2, after: 2, destroy: 1 },
'pipe3, process exiting');
checkInvocations(pipe2, { init: 1, before: 2, after: 2, destroy: 1 },
'pipe2, process exiting');
}

Просмотреть файл

@ -11,7 +11,8 @@ const initHooks = require('./init-hooks');
const { checkInvocations } = require('./hook-checks');
const net = require('net');
let tcp1, tcp2, tcp3;
let tcp1, tcp2;
let tcpserver;
let tcpconnect;
const hooks = initHooks();
@ -24,15 +25,15 @@ const server = net
// Calling server.listen creates a TCPWRAP synchronously
{
server.listen(common.PORT);
const tcps = hooks.activitiesOfTypes('TCPWRAP');
const tcpsservers = hooks.activitiesOfTypes('TCPSERVERWRAP');
const tcpconnects = hooks.activitiesOfTypes('TCPCONNECTWRAP');
assert.strictEqual(tcps.length, 1);
assert.strictEqual(tcpsservers.length, 1);
assert.strictEqual(tcpconnects.length, 0);
tcp1 = tcps[0];
assert.strictEqual(tcp1.type, 'TCPWRAP');
assert.strictEqual(typeof tcp1.uid, 'number');
assert.strictEqual(typeof tcp1.triggerAsyncId, 'number');
checkInvocations(tcp1, { init: 1 }, 'when calling server.listen');
tcpserver = tcpsservers[0];
assert.strictEqual(tcpserver.type, 'TCPSERVERWRAP');
assert.strictEqual(typeof tcpserver.uid, 'number');
assert.strictEqual(typeof tcpserver.triggerAsyncId, 'number');
checkInvocations(tcpserver, { init: 1 }, 'when calling server.listen');
}
// Calling net.connect creates another TCPWRAP synchronously
@ -41,24 +42,25 @@ const server = net
{ port: server.address().port, host: '::1' },
common.mustCall(onconnected));
const tcps = hooks.activitiesOfTypes('TCPWRAP');
assert.strictEqual(tcps.length, 2);
assert.strictEqual(tcps.length, 1);
process.nextTick(() => {
const tcpconnects = hooks.activitiesOfTypes('TCPCONNECTWRAP');
assert.strictEqual(tcpconnects.length, 1);
});
tcp2 = tcps[1];
assert.strictEqual(tcps.length, 2);
assert.strictEqual(tcp2.type, 'TCPWRAP');
assert.strictEqual(typeof tcp2.uid, 'number');
assert.strictEqual(typeof tcp2.triggerAsyncId, 'number');
tcp1 = tcps[0];
assert.strictEqual(tcps.length, 1);
assert.strictEqual(tcp1.type, 'TCPWRAP');
assert.strictEqual(typeof tcp1.uid, 'number');
assert.strictEqual(typeof tcp1.triggerAsyncId, 'number');
checkInvocations(tcpserver, { init: 1 },
'tcpserver when client is connecting');
checkInvocations(tcp1, { init: 1 }, 'tcp1 when client is connecting');
checkInvocations(tcp2, { init: 1 }, 'tcp2 when client is connecting');
}
function onlistening() {
assert.strictEqual(hooks.activitiesOfTypes('TCPWRAP').length, 2);
assert.strictEqual(hooks.activitiesOfTypes('TCPWRAP').length, 1);
}
// Depending on timing we see client: onconnected or server: onconnection first
@ -99,8 +101,8 @@ function onconnected() {
const expected = serverConnected ?
{ init: 1, before: 1, after: 1 } :
{ init: 1 };
checkInvocations(tcp1, expected, 'tcp1 when client connects');
checkInvocations(tcp2, { init: 1 }, 'tcp2 when client connects');
checkInvocations(tcpserver, expected, 'tcpserver when client connects');
checkInvocations(tcp1, { init: 1 }, 'tcp1 when client connects');
}
function onconnection(c) {
@ -109,34 +111,35 @@ function onconnection(c) {
const tcps = hooks.activitiesOfTypes([ 'TCPWRAP' ]);
const tcpconnects = hooks.activitiesOfTypes('TCPCONNECTWRAP');
assert.strictEqual(tcps.length, 3);
assert.strictEqual(tcps.length, 2);
assert.strictEqual(tcpconnects.length, 1);
tcp3 = tcps[2];
assert.strictEqual(tcp3.type, 'TCPWRAP');
assert.strictEqual(typeof tcp3.uid, 'number');
assert.strictEqual(typeof tcp3.triggerAsyncId, 'number');
tcp2 = tcps[1];
assert.strictEqual(tcp2.type, 'TCPWRAP');
assert.strictEqual(typeof tcp2.uid, 'number');
assert.strictEqual(typeof tcp2.triggerAsyncId, 'number');
checkInvocations(tcp1, { init: 1, before: 1 },
'tcp1 when server receives connection');
checkInvocations(tcpserver, { init: 1, before: 1 },
'tcpserver when server receives connection');
checkInvocations(tcp1, { init: 1 }, 'tcp1 when server receives connection');
checkInvocations(tcp2, { init: 1 }, 'tcp2 when server receives connection');
checkInvocations(tcp3, { init: 1 }, 'tcp3 when server receives connection');
c.end();
this.close(common.mustCall(onserverClosed));
}
function onserverClosed() {
checkInvocations(tcp1, { init: 1, before: 1, after: 1, destroy: 1 },
'tcp1 when server is closed');
checkInvocations(tcpserver, { init: 1, before: 1, after: 1, destroy: 1 },
'tcpserver when server is closed');
setImmediate(() => {
checkInvocations(tcp2, { init: 1, before: 2, after: 2, destroy: 1 },
'tcp2 after server is closed');
checkInvocations(tcp1, { init: 1, before: 2, after: 2, destroy: 1 },
'tcp1 after server is closed');
});
checkInvocations(tcp3, { init: 1, before: 1, after: 1 },
'tcp3 synchronously when server is closed');
checkInvocations(tcp2, { init: 1, before: 1, after: 1 },
'tcp2 synchronously when server is closed');
tick(2, () => {
checkInvocations(tcp3, { init: 1, before: 2, after: 2, destroy: 1 },
'tcp3 when server is closed');
checkInvocations(tcp2, { init: 1, before: 2, after: 2, destroy: 1 },
'tcp2 when server is closed');
checkInvocations(tcpconnect, { init: 1, before: 1, after: 1, destroy: 1 },
'tcpconnect when server is closed');
});
@ -146,16 +149,16 @@ process.on('exit', onexit);
function onexit() {
hooks.disable();
hooks.sanityCheck([ 'TCPWRAP', 'TCPCONNECTWRAP' ]);
hooks.sanityCheck([ 'TCPWRAP', 'TCPSERVERWRAP', 'TCPCONNECTWRAP' ]);
checkInvocations(tcp1, { init: 1, before: 1, after: 1, destroy: 1 },
'tcp1 when process exits');
checkInvocations(tcpserver, { init: 1, before: 1, after: 1, destroy: 1 },
'tcpserver when process exits');
checkInvocations(
tcp1, { init: 1, before: 2, after: 2, destroy: 1 },
'tcp1 when process exits');
checkInvocations(
tcp2, { init: 1, before: 2, after: 2, destroy: 1 },
'tcp2 when process exits');
checkInvocations(
tcp3, { init: 1, before: 2, after: 2, destroy: 1 },
'tcp3 when process exits');
checkInvocations(
tcpconnect, { init: 1, before: 1, after: 1, destroy: 1 },
'tcpconnect when process exits');

Просмотреть файл

@ -524,8 +524,8 @@ function _mustCallInner(fn, criteria = 1, field) {
}
exports.hasMultiLocalhost = function hasMultiLocalhost() {
const TCP = process.binding('tcp_wrap').TCP;
const t = new TCP();
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
const t = new TCP(TCPConstants.SOCKET);
const ret = t.bind('127.0.0.2', exports.PORT);
t.close();
return ret === 0;

Просмотреть файл

@ -66,8 +66,8 @@ const dgram = require('dgram');
// pipe
{
const Pipe = process.binding('pipe_wrap').Pipe;
const handle = new Pipe();
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
const handle = new Pipe(PipeConstants.SOCKET);
strictEqual(Object.getPrototypeOf(handle).hasOwnProperty('hasRef'),
true, 'pipe_wrap: hasRef() missing');
strictEqual(handle.hasRef(),

Просмотреть файл

@ -6,7 +6,7 @@ if (common.isWindows)
const assert = require('assert');
const net = require('net');
const path = require('path');
const Pipe = process.binding('pipe_wrap').Pipe;
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
common.refreshTmpDir();
@ -71,7 +71,7 @@ const forAllClients = (cb) => common.mustCall(cb, CLIENT_VARIANTS);
})
.listen({ path: serverPath }, common.mustCall(function serverOnListen() {
const getSocketOpt = (index) => {
const handle = new Pipe();
const handle = new Pipe(PipeConstants.SOCKET);
const err = handle.bind(`${prefix}-client-${socketCounter++}`);
assert(err >= 0, String(err));
assert.notStrictEqual(handle.fd, -1);

Просмотреть файл

@ -5,8 +5,8 @@ const assert = require('assert');
const net = require('net');
const fs = require('fs');
const uv = process.binding('uv');
const TCP = process.binding('tcp_wrap').TCP;
const Pipe = process.binding('pipe_wrap').Pipe;
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
common.refreshTmpDir();
@ -36,12 +36,12 @@ function randomPipePath() {
function randomHandle(type) {
let handle, errno, handleName;
if (type === 'tcp') {
handle = new TCP();
handle = new TCP(TCPConstants.SOCKET);
errno = handle.bind('0.0.0.0', 0);
handleName = 'arbitrary tcp port';
} else {
const path = randomPipePath();
handle = new Pipe();
handle = new Pipe(PipeConstants.SOCKET);
errno = handle.bind(path);
handleName = `pipe ${path}`;
}

Просмотреть файл

@ -23,8 +23,8 @@
require('../common');
const assert = require('assert');
const Process = process.binding('process_wrap').Process;
const Pipe = process.binding('pipe_wrap').Pipe;
const pipe = new Pipe();
const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap');
const pipe = new Pipe(PipeConstants.SOCKET);
const p = new Process();
let processExited = false;

Просмотреть файл

@ -1,12 +1,12 @@
'use strict';
require('../common');
const assert = require('assert');
const TCP = process.binding('tcp_wrap').TCP;
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
const TCPConnectWrap = process.binding('tcp_wrap').TCPConnectWrap;
const ShutdownWrap = process.binding('stream_wrap').ShutdownWrap;
function makeConnection() {
const client = new TCP();
const client = new TCP(TCPConstants.SOCKET);
const req = new TCPConnectWrap();
const err = client.connect(req, '127.0.0.1', this.address().port);

Просмотреть файл

@ -2,10 +2,10 @@
const common = require('../common');
const assert = require('assert');
const TCP = process.binding('tcp_wrap').TCP;
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
const WriteWrap = process.binding('stream_wrap').WriteWrap;
const server = new TCP();
const server = new TCP(TCPConstants.SOCKET);
const r = server.bind('0.0.0.0', 0);
assert.strictEqual(0, r);

Просмотреть файл

@ -23,10 +23,10 @@
require('../common');
const assert = require('assert');
const TCP = process.binding('tcp_wrap').TCP;
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
const uv = process.binding('uv');
const handle = new TCP();
const handle = new TCP(TCPConstants.SOCKET);
// Should be able to bind to the port
let err = handle.bind('0.0.0.0', 0);

Просмотреть файл

@ -138,19 +138,27 @@ if (common.hasCrypto) { // eslint-disable-line crypto-check
testInitialized(new Gzip()._handle, 'Zlib');
}
{
const binding = process.binding('pipe_wrap');
const handle = new binding.Pipe();
const handle = new binding.Pipe(binding.constants.IPC);
testInitialized(handle, 'Pipe');
const req = new binding.PipeConnectWrap();
testUninitialized(req, 'PipeConnectWrap');
req.address = common.PIPE;
req.oncomplete = common.mustCall(() => handle.close());
handle.connect(req, req.address, req.oncomplete);
testInitialized(req, 'PipeConnectWrap');
}
{
const server = net.createServer(common.mustCall((socket) => {
server.close();
})).listen(common.PIPE, common.mustCall(() => {
const binding = process.binding('pipe_wrap');
const handle = new binding.Pipe(binding.constants.SOCKET);
testInitialized(handle, 'Pipe');
const req = new binding.PipeConnectWrap();
testUninitialized(req, 'PipeConnectWrap');
req.address = common.PIPE;
req.oncomplete = common.mustCall(() => handle.close());
handle.connect(req, req.address, req.oncomplete);
testInitialized(req, 'PipeConnectWrap');
}));
}
{
const Process = process.binding('process_wrap').Process;
@ -179,7 +187,7 @@ if (common.hasCrypto) { // eslint-disable-line crypto-check
});
socket.resume();
})).listen(0, common.localhostIPv4, common.mustCall(() => {
const handle = new tcp_wrap.TCP();
const handle = new tcp_wrap.TCP(tcp_wrap.constants.SOCKET);
const req = new tcp_wrap.TCPConnectWrap();
const sreq = new stream_wrap.ShutdownWrap();
const wreq = new stream_wrap.WriteWrap();
@ -221,8 +229,8 @@ if (common.hasCrypto) { // eslint-disable-line crypto-check
if (common.hasCrypto) { // eslint-disable-line crypto-check
const TCP = process.binding('tcp_wrap').TCP;
const tcp = new TCP();
const { TCP, constants: TCPConstants } = process.binding('tcp_wrap');
const tcp = new TCP(TCPConstants.SOCKET);
const ca = fixtures.readSync('test_ca.pem', 'ascii');
const cert = fixtures.readSync('test_cert.pem', 'ascii');