net: do not inherit the no-half-open enforcer

`Socket.prototype.destroySoon()` is called as soon as `UV_EOF` is read
if the `allowHalfOpen` option is disabled. This already works as a
"no-half-open enforcer" so there is no need to inherit another from
`stream.Duplex`.

PR-URL: https://github.com/nodejs/node/pull/18974
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Chen Gang <gangc.cxy@foxmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
This commit is contained in:
Luigi Pinca 2018-02-24 09:44:42 +01:00
parent df0716921e
commit 4e86f9b5ab
3 changed files with 19 additions and 10 deletions

View File

@ -64,6 +64,7 @@ const {
ERR_SOCKET_BAD_PORT, ERR_SOCKET_BAD_PORT,
ERR_SOCKET_CLOSED ERR_SOCKET_CLOSED
} = errors.codes; } = errors.codes;
const DuplexBase = require('internal/streams/duplex_base');
const dns = require('dns'); const dns = require('dns');
const kLastWriteQueueSize = Symbol('lastWriteQueueSize'); const kLastWriteQueueSize = Symbol('lastWriteQueueSize');
@ -238,7 +239,11 @@ function Socket(options) {
// For backwards compat do not emit close on destroy. // For backwards compat do not emit close on destroy.
options.emitClose = false; options.emitClose = false;
stream.Duplex.call(this, options); // `DuplexBase` is just a slimmed down constructor for `Duplex` which allow
// us to not inherit the "no-half-open enforcer" as there is already one in
// place. Instances of `Socket` are still instances of `Duplex`, that is,
// `socket instanceof Duplex === true`.
DuplexBase.call(this, options);
if (options.handle) { if (options.handle) {
this._handle = options.handle; // private this._handle = options.handle; // private
@ -263,8 +268,6 @@ function Socket(options) {
this._writev = null; this._writev = null;
this._write = makeSyncWrite(fd); this._write = makeSyncWrite(fd);
} }
this.readable = options.readable !== false;
this.writable = options.writable !== false;
} else { } else {
// these will be set once there is a connection // these will be set once there is a connection
this.readable = this.writable = false; this.readable = this.writable = false;
@ -282,7 +285,7 @@ function Socket(options) {
this._writableState.decodeStrings = false; this._writableState.decodeStrings = false;
// default to *not* allowing half open sockets // default to *not* allowing half open sockets
this.allowHalfOpen = options && options.allowHalfOpen || false; this.allowHalfOpen = options.allowHalfOpen || false;
// if we have a handle, then start the flow of data into the // if we have a handle, then start the flow of data into the
// buffer. if not, then this will happen when we connect // buffer. if not, then this will happen when we connect

View File

@ -75,12 +75,7 @@ server.listen(0, common.mustCall(() => {
assert.strictEqual(socket.listeners('connect').length, 0); assert.strictEqual(socket.listeners('connect').length, 0);
assert.strictEqual(socket.listeners('data').length, 0); assert.strictEqual(socket.listeners('data').length, 0);
assert.strictEqual(socket.listeners('drain').length, 0); assert.strictEqual(socket.listeners('drain').length, 0);
assert.strictEqual(socket.listeners('end').length, 1);
// the stream.Duplex onend listener
// allow 0 here, so that i can run the same test on streams1 impl
assert(socket.listenerCount('end') <= 2,
`Found ${socket.listenerCount('end')} end listeners`);
assert.strictEqual(socket.listeners('free').length, 0); assert.strictEqual(socket.listeners('free').length, 0);
assert.strictEqual(socket.listeners('close').length, 0); assert.strictEqual(socket.listeners('close').length, 0);
assert.strictEqual(socket.listeners('error').length, 0); assert.strictEqual(socket.listeners('error').length, 0);

View File

@ -0,0 +1,11 @@
'use strict';
require('../common');
// This test ensures that `net.Socket` does not inherit the no-half-open
// enforcer from `stream.Duplex`.
const { Socket } = require('net');
const { strictEqual } = require('assert');
const socket = new Socket({ allowHalfOpen: false });
strictEqual(socket.listenerCount('end'), 1);