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