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