11cb0ef41Sopenharmony_ci// Flags: --expose-internals 21cb0ef41Sopenharmony_ci'use strict'; 31cb0ef41Sopenharmony_ciconst common = require('../common'); 41cb0ef41Sopenharmony_ciif (common.isWindows) 51cb0ef41Sopenharmony_ci common.skip('Does not support wrapping sockets with fd on Windows'); 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ciconst assert = require('assert'); 81cb0ef41Sopenharmony_ciconst net = require('net'); 91cb0ef41Sopenharmony_ciconst path = require('path'); 101cb0ef41Sopenharmony_ciconst { internalBinding } = require('internal/test/binding'); 111cb0ef41Sopenharmony_ciconst { Pipe, constants: PipeConstants } = internalBinding('pipe_wrap'); 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ciconst tmpdir = require('../common/tmpdir'); 141cb0ef41Sopenharmony_citmpdir.refresh(); 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_cifunction testClients(getSocketOpt, getConnectOpt, getConnectCb) { 171cb0ef41Sopenharmony_ci const cloneOptions = (index) => 181cb0ef41Sopenharmony_ci ({ ...getSocketOpt(index), ...getConnectOpt(index) }); 191cb0ef41Sopenharmony_ci return [ 201cb0ef41Sopenharmony_ci net.connect(cloneOptions(0), getConnectCb(0)), 211cb0ef41Sopenharmony_ci net.connect(cloneOptions(1)) 221cb0ef41Sopenharmony_ci .on('connect', getConnectCb(1)), 231cb0ef41Sopenharmony_ci net.createConnection(cloneOptions(2), getConnectCb(2)), 241cb0ef41Sopenharmony_ci net.createConnection(cloneOptions(3)) 251cb0ef41Sopenharmony_ci .on('connect', getConnectCb(3)), 261cb0ef41Sopenharmony_ci new net.Socket(getSocketOpt(4)).connect(getConnectOpt(4), getConnectCb(4)), 271cb0ef41Sopenharmony_ci new net.Socket(getSocketOpt(5)).connect(getConnectOpt(5)) 281cb0ef41Sopenharmony_ci .on('connect', getConnectCb(5)), 291cb0ef41Sopenharmony_ci ]; 301cb0ef41Sopenharmony_ci} 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ciconst CLIENT_VARIANTS = 6; // Same length as array above 331cb0ef41Sopenharmony_ciconst forAllClients = (cb) => common.mustCall(cb, CLIENT_VARIANTS); 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci// Test Pipe fd is wrapped correctly 361cb0ef41Sopenharmony_ci{ 371cb0ef41Sopenharmony_ci // Use relative path to avoid hitting 108-char length limit 381cb0ef41Sopenharmony_ci // for socket paths in libuv. 391cb0ef41Sopenharmony_ci const prefix = path.relative('.', `${common.PIPE}-net-connect-options-fd`); 401cb0ef41Sopenharmony_ci const serverPath = `${prefix}-server`; 411cb0ef41Sopenharmony_ci let counter = 0; 421cb0ef41Sopenharmony_ci let socketCounter = 0; 431cb0ef41Sopenharmony_ci const handleMap = new Map(); 441cb0ef41Sopenharmony_ci const server = net.createServer() 451cb0ef41Sopenharmony_ci .on('connection', forAllClients(function serverOnConnection(socket) { 461cb0ef41Sopenharmony_ci let clientFd; 471cb0ef41Sopenharmony_ci socket.on('data', common.mustCall(function(data) { 481cb0ef41Sopenharmony_ci clientFd = data.toString(); 491cb0ef41Sopenharmony_ci console.error(`[Pipe]Received data from fd ${clientFd}`); 501cb0ef41Sopenharmony_ci socket.end(); 511cb0ef41Sopenharmony_ci })); 521cb0ef41Sopenharmony_ci socket.on('end', common.mustCall(function() { 531cb0ef41Sopenharmony_ci counter++; 541cb0ef41Sopenharmony_ci console.error(`[Pipe]Received end from fd ${clientFd}, total ${counter}`); 551cb0ef41Sopenharmony_ci if (counter === CLIENT_VARIANTS) { 561cb0ef41Sopenharmony_ci setTimeout(() => { 571cb0ef41Sopenharmony_ci console.error(`[Pipe]Server closed by fd ${clientFd}`); 581cb0ef41Sopenharmony_ci server.close(); 591cb0ef41Sopenharmony_ci }, 10); 601cb0ef41Sopenharmony_ci } 611cb0ef41Sopenharmony_ci }, 1)); 621cb0ef41Sopenharmony_ci })) 631cb0ef41Sopenharmony_ci .on('close', function() { 641cb0ef41Sopenharmony_ci setTimeout(() => { 651cb0ef41Sopenharmony_ci for (const pair of handleMap) { 661cb0ef41Sopenharmony_ci console.error(`[Pipe]Clean up handle with fd ${pair[1].fd}`); 671cb0ef41Sopenharmony_ci pair[1].close(); // clean up handles 681cb0ef41Sopenharmony_ci } 691cb0ef41Sopenharmony_ci }, 10); 701cb0ef41Sopenharmony_ci }) 711cb0ef41Sopenharmony_ci .on('error', function(err) { 721cb0ef41Sopenharmony_ci console.error(err); 731cb0ef41Sopenharmony_ci assert.fail(`[Pipe server]${err}`); 741cb0ef41Sopenharmony_ci }) 751cb0ef41Sopenharmony_ci .listen({ path: serverPath }, common.mustCall(function serverOnListen() { 761cb0ef41Sopenharmony_ci const getSocketOpt = (index) => { 771cb0ef41Sopenharmony_ci const handle = new Pipe(PipeConstants.SOCKET); 781cb0ef41Sopenharmony_ci const err = handle.bind(`${prefix}-client-${socketCounter++}`); 791cb0ef41Sopenharmony_ci assert(err >= 0, String(err)); 801cb0ef41Sopenharmony_ci assert.notStrictEqual(handle.fd, -1); 811cb0ef41Sopenharmony_ci handleMap.set(index, handle); 821cb0ef41Sopenharmony_ci console.error(`[Pipe]Bound handle with Pipe ${handle.fd}`); 831cb0ef41Sopenharmony_ci return { fd: handle.fd, readable: true, writable: true }; 841cb0ef41Sopenharmony_ci }; 851cb0ef41Sopenharmony_ci const getConnectOpt = () => ({ 861cb0ef41Sopenharmony_ci path: serverPath 871cb0ef41Sopenharmony_ci }); 881cb0ef41Sopenharmony_ci const getConnectCb = (index) => common.mustCall(function clientOnConnect() { 891cb0ef41Sopenharmony_ci // Test if it's wrapping an existing fd 901cb0ef41Sopenharmony_ci assert(handleMap.has(index)); 911cb0ef41Sopenharmony_ci const oldHandle = handleMap.get(index); 921cb0ef41Sopenharmony_ci assert.strictEqual(oldHandle.fd, this._handle.fd); 931cb0ef41Sopenharmony_ci this.write(String(oldHandle.fd)); 941cb0ef41Sopenharmony_ci console.error(`[Pipe]Sending data through fd ${oldHandle.fd}`); 951cb0ef41Sopenharmony_ci this.on('error', function(err) { 961cb0ef41Sopenharmony_ci console.error(err); 971cb0ef41Sopenharmony_ci assert.fail(`[Pipe Client]${err}`); 981cb0ef41Sopenharmony_ci }); 991cb0ef41Sopenharmony_ci }); 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci testClients(getSocketOpt, getConnectOpt, getConnectCb); 1021cb0ef41Sopenharmony_ci })); 1031cb0ef41Sopenharmony_ci} 104