diff options
author | Ouyang Yadong <oyydoibh@gmail.com> | 2018-10-14 20:13:03 +0800 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2018-10-21 08:56:24 +0200 |
commit | 517955a474877893751d71b33f9c02a21bc25000 (patch) | |
tree | ec4b88bed3396b188830207604042b66ecc60912 /test/parallel/test-wrap-js-stream-destroy.js | |
parent | beb0f03e78a8fab01169213aafeebf9fabf1db43 (diff) | |
download | node-new-517955a474877893751d71b33f9c02a21bc25000.tar.gz |
tls: close StreamWrap and its stream correctly
When sockets of the "net" module destroyed, they will call
`this._handle.close()` which will also emit EOF if not emitted
before. This feature makes sockets on the other side emit "end" and
"close" even though we haven't called `end()`. As `stream` of
`StreamWrap` are likely to be instances of `net.Socket`, calling
`destroy()` manually will avoid issues that don't properly close
wrapped connections.
Fixes: https://github.com/nodejs/node/issues/14605
PR-URL: https://github.com/nodejs/node/pull/23654
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'test/parallel/test-wrap-js-stream-destroy.js')
-rw-r--r-- | test/parallel/test-wrap-js-stream-destroy.js | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/test/parallel/test-wrap-js-stream-destroy.js b/test/parallel/test-wrap-js-stream-destroy.js new file mode 100644 index 0000000000..16d3e75e2c --- /dev/null +++ b/test/parallel/test-wrap-js-stream-destroy.js @@ -0,0 +1,118 @@ +'use strict'; + +const common = require('../common'); +const StreamWrap = require('_stream_wrap'); +const net = require('net'); + +// This test ensures that when we directly call `socket.destroy()` without +// having called `socket.end()` on an instance of streamWrap, it will +// still emit EOF which makes the socket on the other side emit "end" and +// "close" events, and vice versa. +{ + let port; + const server = net.createServer((socket) => { + socket.on('error', common.mustNotCall()); + socket.on('end', common.mustNotCall()); + socket.on('close', common.mustCall()); + socket.destroy(); + }); + + server.listen(() => { + port = server.address().port; + createSocket(); + }); + + function createSocket() { + let streamWrap; + const socket = new net.connect({ + port, + }, () => { + socket.on('error', common.mustNotCall()); + socket.on('end', common.mustCall()); + socket.on('close', common.mustCall()); + + streamWrap.on('error', common.mustNotCall()); + // The "end" events will be emitted which is as same as + // the same situation for an instance of `net.Socket` without + // `StreamWrap`. + streamWrap.on('end', common.mustCall()); + // Destroying a socket in the server side should emit EOF and cause + // the corresponding client-side socket closed. + streamWrap.on('close', common.mustCall(() => { + server.close(); + })); + }); + streamWrap = new StreamWrap(socket); + } +} + +// Destroy the streamWrap and test again. +{ + let port; + const server = net.createServer((socket) => { + socket.on('error', common.mustNotCall()); + socket.on('end', common.mustCall()); + socket.on('close', common.mustCall(() => { + server.close(); + })); + // Do not `socket.end()` and directly `socket.destroy()`. + }); + + server.listen(() => { + port = server.address().port; + createSocket(); + }); + + function createSocket() { + let streamWrap; + const socket = new net.connect({ + port, + }, () => { + socket.on('error', common.mustNotCall()); + socket.on('end', common.mustNotCall()); + socket.on('close', common.mustCall()); + + streamWrap.on('error', common.mustNotCall()); + streamWrap.on('end', common.mustNotCall()); + // Destroying a socket in the server side should emit EOF and cause + // the corresponding client-side socket closed. + streamWrap.on('close', common.mustCall()); + streamWrap.destroy(); + }); + streamWrap = new StreamWrap(socket); + } +} + +// Destroy the client socket and test again. +{ + let port; + const server = net.createServer((socket) => { + socket.on('error', common.mustNotCall()); + socket.on('end', common.mustCall()); + socket.on('close', common.mustCall(() => { + server.close(); + })); + }); + + server.listen(() => { + port = server.address().port; + createSocket(); + }); + + function createSocket() { + let streamWrap; + const socket = new net.connect({ + port, + }, () => { + socket.on('error', common.mustNotCall()); + socket.on('end', common.mustNotCall()); + socket.on('close', common.mustCall()); + + streamWrap.on('error', common.mustNotCall()); + streamWrap.on('end', common.mustNotCall()); + streamWrap.on('close', common.mustCall()); + socket.destroy(); + }); + streamWrap = new StreamWrap(socket); + } +} |