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 dns = require('dns');
261cb0ef41Sopenharmony_ciconst net = require('net');
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci// Test wrong type of ports
291cb0ef41Sopenharmony_ci{
301cb0ef41Sopenharmony_ci  const portTypeError = {
311cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE',
321cb0ef41Sopenharmony_ci    name: 'TypeError'
331cb0ef41Sopenharmony_ci  };
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  syncFailToConnect(true, portTypeError);
361cb0ef41Sopenharmony_ci  syncFailToConnect(false, portTypeError);
371cb0ef41Sopenharmony_ci  syncFailToConnect([], portTypeError, true);
381cb0ef41Sopenharmony_ci  syncFailToConnect({}, portTypeError, true);
391cb0ef41Sopenharmony_ci  syncFailToConnect(null, portTypeError);
401cb0ef41Sopenharmony_ci}
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci// Test out of range ports
431cb0ef41Sopenharmony_ci{
441cb0ef41Sopenharmony_ci  const portRangeError = {
451cb0ef41Sopenharmony_ci    code: 'ERR_SOCKET_BAD_PORT',
461cb0ef41Sopenharmony_ci    name: 'RangeError'
471cb0ef41Sopenharmony_ci  };
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci  syncFailToConnect('', portRangeError);
501cb0ef41Sopenharmony_ci  syncFailToConnect(' ', portRangeError);
511cb0ef41Sopenharmony_ci  syncFailToConnect('0x', portRangeError, true);
521cb0ef41Sopenharmony_ci  syncFailToConnect('-0x1', portRangeError, true);
531cb0ef41Sopenharmony_ci  syncFailToConnect(NaN, portRangeError);
541cb0ef41Sopenharmony_ci  syncFailToConnect(Infinity, portRangeError);
551cb0ef41Sopenharmony_ci  syncFailToConnect(-1, portRangeError);
561cb0ef41Sopenharmony_ci  syncFailToConnect(65536, portRangeError);
571cb0ef41Sopenharmony_ci}
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci// Test invalid hints
601cb0ef41Sopenharmony_ci{
611cb0ef41Sopenharmony_ci  // connect({hint}, cb) and connect({hint})
621cb0ef41Sopenharmony_ci  const hints = (dns.ADDRCONFIG | dns.V4MAPPED | dns.ALL) + 42;
631cb0ef41Sopenharmony_ci  const hintOptBlocks = doConnect([{ port: 42, hints }],
641cb0ef41Sopenharmony_ci                                  () => common.mustNotCall());
651cb0ef41Sopenharmony_ci  for (const fn of hintOptBlocks) {
661cb0ef41Sopenharmony_ci    assert.throws(fn, {
671cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_VALUE',
681cb0ef41Sopenharmony_ci      name: 'TypeError',
691cb0ef41Sopenharmony_ci      message: /The argument 'hints' is invalid\. Received \d+/
701cb0ef41Sopenharmony_ci    });
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci}
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci// Test valid combinations of connect(port) and connect(port, host)
751cb0ef41Sopenharmony_ci{
761cb0ef41Sopenharmony_ci  const expectedConnections = 72;
771cb0ef41Sopenharmony_ci  let serverConnected = 0;
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  const server = net.createServer(common.mustCall((socket) => {
801cb0ef41Sopenharmony_ci    socket.end('ok');
811cb0ef41Sopenharmony_ci    if (++serverConnected === expectedConnections) {
821cb0ef41Sopenharmony_ci      server.close();
831cb0ef41Sopenharmony_ci    }
841cb0ef41Sopenharmony_ci  }, expectedConnections));
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  server.listen(0, common.localhostIPv4, common.mustCall(() => {
871cb0ef41Sopenharmony_ci    const port = server.address().port;
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci    // Total connections = 3 * 4(canConnect) * 6(doConnect) = 72
901cb0ef41Sopenharmony_ci    canConnect(port);
911cb0ef41Sopenharmony_ci    canConnect(String(port));
921cb0ef41Sopenharmony_ci    canConnect(`0x${port.toString(16)}`);
931cb0ef41Sopenharmony_ci  }));
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  // Try connecting to random ports, but do so once the server is closed
961cb0ef41Sopenharmony_ci  server.on('close', () => {
971cb0ef41Sopenharmony_ci    asyncFailToConnect(0);
981cb0ef41Sopenharmony_ci  });
991cb0ef41Sopenharmony_ci}
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_cifunction doConnect(args, getCb) {
1021cb0ef41Sopenharmony_ci  return [
1031cb0ef41Sopenharmony_ci    function createConnectionWithCb() {
1041cb0ef41Sopenharmony_ci      return net.createConnection.apply(net, args.concat(getCb()))
1051cb0ef41Sopenharmony_ci        .resume();
1061cb0ef41Sopenharmony_ci    },
1071cb0ef41Sopenharmony_ci    function createConnectionWithoutCb() {
1081cb0ef41Sopenharmony_ci      return net.createConnection.apply(net, args)
1091cb0ef41Sopenharmony_ci        .on('connect', getCb())
1101cb0ef41Sopenharmony_ci        .resume();
1111cb0ef41Sopenharmony_ci    },
1121cb0ef41Sopenharmony_ci    function connectWithCb() {
1131cb0ef41Sopenharmony_ci      return net.connect.apply(net, args.concat(getCb()))
1141cb0ef41Sopenharmony_ci        .resume();
1151cb0ef41Sopenharmony_ci    },
1161cb0ef41Sopenharmony_ci    function connectWithoutCb() {
1171cb0ef41Sopenharmony_ci      return net.connect.apply(net, args)
1181cb0ef41Sopenharmony_ci        .on('connect', getCb())
1191cb0ef41Sopenharmony_ci        .resume();
1201cb0ef41Sopenharmony_ci    },
1211cb0ef41Sopenharmony_ci    function socketConnectWithCb() {
1221cb0ef41Sopenharmony_ci      const socket = new net.Socket();
1231cb0ef41Sopenharmony_ci      return socket.connect.apply(socket, args.concat(getCb()))
1241cb0ef41Sopenharmony_ci        .resume();
1251cb0ef41Sopenharmony_ci    },
1261cb0ef41Sopenharmony_ci    function socketConnectWithoutCb() {
1271cb0ef41Sopenharmony_ci      const socket = new net.Socket();
1281cb0ef41Sopenharmony_ci      return socket.connect.apply(socket, args)
1291cb0ef41Sopenharmony_ci        .on('connect', getCb())
1301cb0ef41Sopenharmony_ci        .resume();
1311cb0ef41Sopenharmony_ci    },
1321cb0ef41Sopenharmony_ci  ];
1331cb0ef41Sopenharmony_ci}
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_cifunction syncFailToConnect(port, assertErr, optOnly) {
1361cb0ef41Sopenharmony_ci  const family = 4;
1371cb0ef41Sopenharmony_ci  if (!optOnly) {
1381cb0ef41Sopenharmony_ci    // connect(port, cb) and connect(port)
1391cb0ef41Sopenharmony_ci    const portArgFunctions = doConnect([{ port, family }],
1401cb0ef41Sopenharmony_ci                                       () => common.mustNotCall());
1411cb0ef41Sopenharmony_ci    for (const fn of portArgFunctions) {
1421cb0ef41Sopenharmony_ci      assert.throws(fn, assertErr, `${fn.name}(${port})`);
1431cb0ef41Sopenharmony_ci    }
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci    // connect(port, host, cb) and connect(port, host)
1461cb0ef41Sopenharmony_ci    const portHostArgFunctions = doConnect([{ port,
1471cb0ef41Sopenharmony_ci                                              host: 'localhost',
1481cb0ef41Sopenharmony_ci                                              family }],
1491cb0ef41Sopenharmony_ci                                           () => common.mustNotCall());
1501cb0ef41Sopenharmony_ci    for (const fn of portHostArgFunctions) {
1511cb0ef41Sopenharmony_ci      assert.throws(fn, assertErr, `${fn.name}(${port}, 'localhost')`);
1521cb0ef41Sopenharmony_ci    }
1531cb0ef41Sopenharmony_ci  }
1541cb0ef41Sopenharmony_ci  // connect({port}, cb) and connect({port})
1551cb0ef41Sopenharmony_ci  const portOptFunctions = doConnect([{ port, family }],
1561cb0ef41Sopenharmony_ci                                     () => common.mustNotCall());
1571cb0ef41Sopenharmony_ci  for (const fn of portOptFunctions) {
1581cb0ef41Sopenharmony_ci    assert.throws(fn, assertErr, `${fn.name}({port: ${port}})`);
1591cb0ef41Sopenharmony_ci  }
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci  // connect({port, host}, cb) and connect({port, host})
1621cb0ef41Sopenharmony_ci  const portHostOptFunctions = doConnect([{ port: port,
1631cb0ef41Sopenharmony_ci                                            host: 'localhost',
1641cb0ef41Sopenharmony_ci                                            family: family }],
1651cb0ef41Sopenharmony_ci                                         () => common.mustNotCall());
1661cb0ef41Sopenharmony_ci  for (const fn of portHostOptFunctions) {
1671cb0ef41Sopenharmony_ci    assert.throws(fn,
1681cb0ef41Sopenharmony_ci                  assertErr,
1691cb0ef41Sopenharmony_ci                  `${fn.name}({port: ${port}, host: 'localhost'})`);
1701cb0ef41Sopenharmony_ci  }
1711cb0ef41Sopenharmony_ci}
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_cifunction canConnect(port) {
1741cb0ef41Sopenharmony_ci  const noop = () => common.mustCall();
1751cb0ef41Sopenharmony_ci  const family = 4;
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  // connect(port, cb) and connect(port)
1781cb0ef41Sopenharmony_ci  const portArgFunctions = doConnect([{ port, family }], noop);
1791cb0ef41Sopenharmony_ci  for (const fn of portArgFunctions) {
1801cb0ef41Sopenharmony_ci    fn();
1811cb0ef41Sopenharmony_ci  }
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci  // connect(port, host, cb) and connect(port, host)
1841cb0ef41Sopenharmony_ci  const portHostArgFunctions = doConnect([{ port, host: 'localhost', family }],
1851cb0ef41Sopenharmony_ci                                         noop);
1861cb0ef41Sopenharmony_ci  for (const fn of portHostArgFunctions) {
1871cb0ef41Sopenharmony_ci    fn();
1881cb0ef41Sopenharmony_ci  }
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci  // connect({port}, cb) and connect({port})
1911cb0ef41Sopenharmony_ci  const portOptFunctions = doConnect([{ port, family }], noop);
1921cb0ef41Sopenharmony_ci  for (const fn of portOptFunctions) {
1931cb0ef41Sopenharmony_ci    fn();
1941cb0ef41Sopenharmony_ci  }
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci  // connect({port, host}, cb) and connect({port, host})
1971cb0ef41Sopenharmony_ci  const portHostOptFns = doConnect([{ port, host: 'localhost', family }],
1981cb0ef41Sopenharmony_ci                                   noop);
1991cb0ef41Sopenharmony_ci  for (const fn of portHostOptFns) {
2001cb0ef41Sopenharmony_ci    fn();
2011cb0ef41Sopenharmony_ci  }
2021cb0ef41Sopenharmony_ci}
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_cifunction asyncFailToConnect(port) {
2051cb0ef41Sopenharmony_ci  const onError = () => common.mustCall((err) => {
2061cb0ef41Sopenharmony_ci    const regexp = /^Error: connect E\w+.+$/;
2071cb0ef41Sopenharmony_ci    assert.match(String(err), regexp);
2081cb0ef41Sopenharmony_ci  });
2091cb0ef41Sopenharmony_ci
2101cb0ef41Sopenharmony_ci  const dont = () => common.mustNotCall();
2111cb0ef41Sopenharmony_ci  const family = 4;
2121cb0ef41Sopenharmony_ci  // connect(port, cb) and connect(port)
2131cb0ef41Sopenharmony_ci  const portArgFunctions = doConnect([{ port, family }], dont);
2141cb0ef41Sopenharmony_ci  for (const fn of portArgFunctions) {
2151cb0ef41Sopenharmony_ci    fn().on('error', onError());
2161cb0ef41Sopenharmony_ci  }
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci  // connect({port}, cb) and connect({port})
2191cb0ef41Sopenharmony_ci  const portOptFunctions = doConnect([{ port, family }], dont);
2201cb0ef41Sopenharmony_ci  for (const fn of portOptFunctions) {
2211cb0ef41Sopenharmony_ci    fn().on('error', onError());
2221cb0ef41Sopenharmony_ci  }
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci  // connect({port, host}, cb) and connect({port, host})
2251cb0ef41Sopenharmony_ci  const portHostOptFns = doConnect([{ port, host: 'localhost', family }],
2261cb0ef41Sopenharmony_ci                                   dont);
2271cb0ef41Sopenharmony_ci  for (const fn of portHostOptFns) {
2281cb0ef41Sopenharmony_ci    fn().on('error', onError());
2291cb0ef41Sopenharmony_ci  }
2301cb0ef41Sopenharmony_ci}
231