11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors. 21cb0ef41Sopenharmony_ci// 31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a 41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the 51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including 61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish, 71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit 81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the 91cb0ef41Sopenharmony_ci// following conditions: 101cb0ef41Sopenharmony_ci// 111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included 121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software. 131cb0ef41Sopenharmony_ci// 141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE. 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci'use strict'; 231cb0ef41Sopenharmony_ciconst common = require('../common'); 241cb0ef41Sopenharmony_ciconst assert = require('assert'); 251cb0ef41Sopenharmony_ciconst fork = require('child_process').fork; 261cb0ef41Sopenharmony_ciconst net = require('net'); 271cb0ef41Sopenharmony_ciconst count = 12; 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ciif (process.argv[2] === 'child') { 301cb0ef41Sopenharmony_ci const sockets = []; 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci process.on('message', common.mustCall((m, socket) => { 331cb0ef41Sopenharmony_ci function sendClosed(id) { 341cb0ef41Sopenharmony_ci process.send({ id: id, status: 'closed' }); 351cb0ef41Sopenharmony_ci } 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci if (m.cmd === 'new') { 381cb0ef41Sopenharmony_ci assert(socket); 391cb0ef41Sopenharmony_ci assert(socket instanceof net.Socket, 'should be a net.Socket'); 401cb0ef41Sopenharmony_ci sockets.push(socket); 411cb0ef41Sopenharmony_ci } 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci if (m.cmd === 'close') { 441cb0ef41Sopenharmony_ci assert.strictEqual(socket, undefined); 451cb0ef41Sopenharmony_ci if (sockets[m.id].destroyed) { 461cb0ef41Sopenharmony_ci // Workaround for https://github.com/nodejs/node/issues/2610 471cb0ef41Sopenharmony_ci sendClosed(m.id); 481cb0ef41Sopenharmony_ci // End of workaround. When bug is fixed, this code can be used instead: 491cb0ef41Sopenharmony_ci // throw new Error('socket destroyed unexpectedly!'); 501cb0ef41Sopenharmony_ci } else { 511cb0ef41Sopenharmony_ci sockets[m.id].once('close', sendClosed.bind(null, m.id)); 521cb0ef41Sopenharmony_ci sockets[m.id].destroy(); 531cb0ef41Sopenharmony_ci } 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci })); 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci} else { 581cb0ef41Sopenharmony_ci const child = fork(process.argv[1], ['child']); 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci child.on('exit', common.mustCall((code, signal) => { 611cb0ef41Sopenharmony_ci if (!subprocessKilled) { 621cb0ef41Sopenharmony_ci assert.fail('subprocess died unexpectedly! ' + 631cb0ef41Sopenharmony_ci `code: ${code} signal: ${signal}`); 641cb0ef41Sopenharmony_ci } 651cb0ef41Sopenharmony_ci })); 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci const server = net.createServer(); 681cb0ef41Sopenharmony_ci const sockets = []; 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci server.on('connection', common.mustCall((socket) => { 711cb0ef41Sopenharmony_ci child.send({ cmd: 'new' }, socket); 721cb0ef41Sopenharmony_ci sockets.push(socket); 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci if (sockets.length === count) { 751cb0ef41Sopenharmony_ci closeSockets(0); 761cb0ef41Sopenharmony_ci } 771cb0ef41Sopenharmony_ci }, count)); 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci const onClose = common.mustCall(count); 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci server.on('listening', common.mustCall(() => { 821cb0ef41Sopenharmony_ci let j = count; 831cb0ef41Sopenharmony_ci while (j--) { 841cb0ef41Sopenharmony_ci const client = net.connect(server.address().port, '127.0.0.1'); 851cb0ef41Sopenharmony_ci client.on('close', onClose); 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci })); 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci let subprocessKilled = false; 901cb0ef41Sopenharmony_ci function closeSockets(i) { 911cb0ef41Sopenharmony_ci if (i === count) { 921cb0ef41Sopenharmony_ci subprocessKilled = true; 931cb0ef41Sopenharmony_ci server.close(); 941cb0ef41Sopenharmony_ci child.kill(); 951cb0ef41Sopenharmony_ci return; 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci child.once('message', common.mustCall((m) => { 991cb0ef41Sopenharmony_ci assert.strictEqual(m.status, 'closed'); 1001cb0ef41Sopenharmony_ci server.getConnections(common.mustSucceed((num) => { 1011cb0ef41Sopenharmony_ci assert.strictEqual(num, count - (i + 1)); 1021cb0ef41Sopenharmony_ci closeSockets(i + 1); 1031cb0ef41Sopenharmony_ci })); 1041cb0ef41Sopenharmony_ci })); 1051cb0ef41Sopenharmony_ci child.send({ id: i, cmd: 'close' }); 1061cb0ef41Sopenharmony_ci } 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci server.on('close', common.mustCall()); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci server.listen(0, '127.0.0.1'); 1111cb0ef41Sopenharmony_ci} 112