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_ci 241cb0ef41Sopenharmony_ciconst { 251cb0ef41Sopenharmony_ci ArrayIsArray, 261cb0ef41Sopenharmony_ci ArrayPrototypeIndexOf, 271cb0ef41Sopenharmony_ci ArrayPrototypePush, 281cb0ef41Sopenharmony_ci Boolean, 291cb0ef41Sopenharmony_ci FunctionPrototypeBind, 301cb0ef41Sopenharmony_ci FunctionPrototypeCall, 311cb0ef41Sopenharmony_ci MathMax, 321cb0ef41Sopenharmony_ci Number, 331cb0ef41Sopenharmony_ci NumberIsNaN, 341cb0ef41Sopenharmony_ci NumberParseInt, 351cb0ef41Sopenharmony_ci ObjectDefineProperty, 361cb0ef41Sopenharmony_ci ObjectSetPrototypeOf, 371cb0ef41Sopenharmony_ci Symbol, 381cb0ef41Sopenharmony_ci ObjectCreate, 391cb0ef41Sopenharmony_ci SymbolAsyncDispose, 401cb0ef41Sopenharmony_ci} = primordials; 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ciconst EventEmitter = require('events'); 431cb0ef41Sopenharmony_ciconst stream = require('stream'); 441cb0ef41Sopenharmony_cilet debug = require('internal/util/debuglog').debuglog('net', (fn) => { 451cb0ef41Sopenharmony_ci debug = fn; 461cb0ef41Sopenharmony_ci}); 471cb0ef41Sopenharmony_ciconst { 481cb0ef41Sopenharmony_ci kReinitializeHandle, 491cb0ef41Sopenharmony_ci isIP, 501cb0ef41Sopenharmony_ci isIPv4, 511cb0ef41Sopenharmony_ci isIPv6, 521cb0ef41Sopenharmony_ci normalizedArgsSymbol, 531cb0ef41Sopenharmony_ci makeSyncWrite, 541cb0ef41Sopenharmony_ci} = require('internal/net'); 551cb0ef41Sopenharmony_ciconst assert = require('internal/assert'); 561cb0ef41Sopenharmony_ciconst { 571cb0ef41Sopenharmony_ci UV_EADDRINUSE, 581cb0ef41Sopenharmony_ci UV_EINVAL, 591cb0ef41Sopenharmony_ci UV_ENOTCONN, 601cb0ef41Sopenharmony_ci UV_ECANCELED, 611cb0ef41Sopenharmony_ci} = internalBinding('uv'); 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ciconst { Buffer } = require('buffer'); 641cb0ef41Sopenharmony_ciconst { guessHandleType } = internalBinding('util'); 651cb0ef41Sopenharmony_ciconst { ShutdownWrap } = internalBinding('stream_wrap'); 661cb0ef41Sopenharmony_ciconst { 671cb0ef41Sopenharmony_ci TCP, 681cb0ef41Sopenharmony_ci TCPConnectWrap, 691cb0ef41Sopenharmony_ci constants: TCPConstants, 701cb0ef41Sopenharmony_ci} = internalBinding('tcp_wrap'); 711cb0ef41Sopenharmony_ciconst { 721cb0ef41Sopenharmony_ci Pipe, 731cb0ef41Sopenharmony_ci PipeConnectWrap, 741cb0ef41Sopenharmony_ci constants: PipeConstants, 751cb0ef41Sopenharmony_ci} = internalBinding('pipe_wrap'); 761cb0ef41Sopenharmony_ciconst { 771cb0ef41Sopenharmony_ci newAsyncId, 781cb0ef41Sopenharmony_ci defaultTriggerAsyncIdScope, 791cb0ef41Sopenharmony_ci symbols: { async_id_symbol, owner_symbol }, 801cb0ef41Sopenharmony_ci} = require('internal/async_hooks'); 811cb0ef41Sopenharmony_ciconst { 821cb0ef41Sopenharmony_ci writevGeneric, 831cb0ef41Sopenharmony_ci writeGeneric, 841cb0ef41Sopenharmony_ci onStreamRead, 851cb0ef41Sopenharmony_ci kAfterAsyncWrite, 861cb0ef41Sopenharmony_ci kHandle, 871cb0ef41Sopenharmony_ci kUpdateTimer, 881cb0ef41Sopenharmony_ci setStreamTimeout, 891cb0ef41Sopenharmony_ci kBuffer, 901cb0ef41Sopenharmony_ci kBufferCb, 911cb0ef41Sopenharmony_ci kBufferGen, 921cb0ef41Sopenharmony_ci} = require('internal/stream_base_commons'); 931cb0ef41Sopenharmony_ciconst { 941cb0ef41Sopenharmony_ci codes: { 951cb0ef41Sopenharmony_ci ERR_INVALID_ADDRESS_FAMILY, 961cb0ef41Sopenharmony_ci ERR_INVALID_ARG_TYPE, 971cb0ef41Sopenharmony_ci ERR_INVALID_ARG_VALUE, 981cb0ef41Sopenharmony_ci ERR_INVALID_FD_TYPE, 991cb0ef41Sopenharmony_ci ERR_INVALID_IP_ADDRESS, 1001cb0ef41Sopenharmony_ci ERR_INVALID_HANDLE_TYPE, 1011cb0ef41Sopenharmony_ci ERR_SERVER_ALREADY_LISTEN, 1021cb0ef41Sopenharmony_ci ERR_SERVER_NOT_RUNNING, 1031cb0ef41Sopenharmony_ci ERR_SOCKET_CLOSED, 1041cb0ef41Sopenharmony_ci ERR_SOCKET_CLOSED_BEFORE_CONNECTION, 1051cb0ef41Sopenharmony_ci ERR_MISSING_ARGS, 1061cb0ef41Sopenharmony_ci }, 1071cb0ef41Sopenharmony_ci aggregateErrors, 1081cb0ef41Sopenharmony_ci errnoException, 1091cb0ef41Sopenharmony_ci exceptionWithHostPort, 1101cb0ef41Sopenharmony_ci genericNodeError, 1111cb0ef41Sopenharmony_ci uvExceptionWithHostPort, 1121cb0ef41Sopenharmony_ci} = require('internal/errors'); 1131cb0ef41Sopenharmony_ciconst { isUint8Array } = require('internal/util/types'); 1141cb0ef41Sopenharmony_ciconst { queueMicrotask } = require('internal/process/task_queues'); 1151cb0ef41Sopenharmony_ciconst { kEmptyObject, promisify } = require('internal/util'); 1161cb0ef41Sopenharmony_ciconst { 1171cb0ef41Sopenharmony_ci validateAbortSignal, 1181cb0ef41Sopenharmony_ci validateBoolean, 1191cb0ef41Sopenharmony_ci validateFunction, 1201cb0ef41Sopenharmony_ci validateInt32, 1211cb0ef41Sopenharmony_ci validateNumber, 1221cb0ef41Sopenharmony_ci validatePort, 1231cb0ef41Sopenharmony_ci validateString, 1241cb0ef41Sopenharmony_ci} = require('internal/validators'); 1251cb0ef41Sopenharmony_ciconst kLastWriteQueueSize = Symbol('lastWriteQueueSize'); 1261cb0ef41Sopenharmony_ciconst { 1271cb0ef41Sopenharmony_ci DTRACE_NET_SERVER_CONNECTION, 1281cb0ef41Sopenharmony_ci DTRACE_NET_STREAM_END, 1291cb0ef41Sopenharmony_ci} = require('internal/dtrace'); 1301cb0ef41Sopenharmony_ciconst { getOptionValue } = require('internal/options'); 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci// Lazy loaded to improve startup performance. 1331cb0ef41Sopenharmony_cilet cluster; 1341cb0ef41Sopenharmony_cilet dns; 1351cb0ef41Sopenharmony_cilet BlockList; 1361cb0ef41Sopenharmony_cilet SocketAddress; 1371cb0ef41Sopenharmony_cilet autoSelectFamilyDefault = getOptionValue('--enable-network-family-autoselection'); 1381cb0ef41Sopenharmony_cilet autoSelectFamilyAttemptTimeoutDefault = 250; 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ciconst { clearTimeout, setTimeout } = require('timers'); 1411cb0ef41Sopenharmony_ciconst { kTimeout } = require('internal/timers'); 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ciconst DEFAULT_IPV4_ADDR = '0.0.0.0'; 1441cb0ef41Sopenharmony_ciconst DEFAULT_IPV6_ADDR = '::'; 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ciconst isWindows = process.platform === 'win32'; 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ciconst noop = () => {}; 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ciconst kPerfHooksNetConnectContext = Symbol('kPerfHooksNetConnectContext'); 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_cilet netClientSocketChannel; 1531cb0ef41Sopenharmony_cilet netServerSocketChannel; 1541cb0ef41Sopenharmony_cifunction lazyChannels() { 1551cb0ef41Sopenharmony_ci // TODO(joyeecheung): support diagnostics channels in the snapshot. 1561cb0ef41Sopenharmony_ci // For now it is fine to create them lazily when there isn't a snapshot to 1571cb0ef41Sopenharmony_ci // build. If users need the channels they would have to create them first 1581cb0ef41Sopenharmony_ci // before invoking any built-ins that would publish to these channels 1591cb0ef41Sopenharmony_ci // anyway. 1601cb0ef41Sopenharmony_ci if (netClientSocketChannel === undefined) { 1611cb0ef41Sopenharmony_ci const dc = require('diagnostics_channel'); 1621cb0ef41Sopenharmony_ci netClientSocketChannel = dc.channel('net.client.socket'); 1631cb0ef41Sopenharmony_ci netServerSocketChannel = dc.channel('net.server.socket'); 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci} 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ciconst { 1681cb0ef41Sopenharmony_ci hasObserver, 1691cb0ef41Sopenharmony_ci startPerf, 1701cb0ef41Sopenharmony_ci stopPerf, 1711cb0ef41Sopenharmony_ci} = require('internal/perf/observe'); 1721cb0ef41Sopenharmony_ciconst { getDefaultHighWaterMark } = require('internal/streams/state'); 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_cifunction getFlags(ipv6Only) { 1751cb0ef41Sopenharmony_ci return ipv6Only === true ? TCPConstants.UV_TCP_IPV6ONLY : 0; 1761cb0ef41Sopenharmony_ci} 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_cifunction createHandle(fd, is_server) { 1791cb0ef41Sopenharmony_ci validateInt32(fd, 'fd', 0); 1801cb0ef41Sopenharmony_ci const type = guessHandleType(fd); 1811cb0ef41Sopenharmony_ci if (type === 'PIPE') { 1821cb0ef41Sopenharmony_ci return new Pipe( 1831cb0ef41Sopenharmony_ci is_server ? PipeConstants.SERVER : PipeConstants.SOCKET, 1841cb0ef41Sopenharmony_ci ); 1851cb0ef41Sopenharmony_ci } 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci if (type === 'TCP') { 1881cb0ef41Sopenharmony_ci return new TCP( 1891cb0ef41Sopenharmony_ci is_server ? TCPConstants.SERVER : TCPConstants.SOCKET, 1901cb0ef41Sopenharmony_ci ); 1911cb0ef41Sopenharmony_ci } 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ci throw new ERR_INVALID_FD_TYPE(type); 1941cb0ef41Sopenharmony_ci} 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_cifunction getNewAsyncId(handle) { 1981cb0ef41Sopenharmony_ci return (!handle || typeof handle.getAsyncId !== 'function') ? 1991cb0ef41Sopenharmony_ci newAsyncId() : handle.getAsyncId(); 2001cb0ef41Sopenharmony_ci} 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_cifunction isPipeName(s) { 2041cb0ef41Sopenharmony_ci return typeof s === 'string' && toNumber(s) === false; 2051cb0ef41Sopenharmony_ci} 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci/** 2081cb0ef41Sopenharmony_ci * Creates a new TCP or IPC server 2091cb0ef41Sopenharmony_ci * @param {{ 2101cb0ef41Sopenharmony_ci * allowHalfOpen?: boolean; 2111cb0ef41Sopenharmony_ci * pauseOnConnect?: boolean; 2121cb0ef41Sopenharmony_ci * }} [options] 2131cb0ef41Sopenharmony_ci * @param {Function} [connectionListener] 2141cb0ef41Sopenharmony_ci * @returns {Server} 2151cb0ef41Sopenharmony_ci */ 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_cifunction createServer(options, connectionListener) { 2181cb0ef41Sopenharmony_ci return new Server(options, connectionListener); 2191cb0ef41Sopenharmony_ci} 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci// Target API: 2231cb0ef41Sopenharmony_ci// 2241cb0ef41Sopenharmony_ci// let s = net.connect({port: 80, host: 'google.com'}, function() { 2251cb0ef41Sopenharmony_ci// ... 2261cb0ef41Sopenharmony_ci// }); 2271cb0ef41Sopenharmony_ci// 2281cb0ef41Sopenharmony_ci// There are various forms: 2291cb0ef41Sopenharmony_ci// 2301cb0ef41Sopenharmony_ci// connect(options, [cb]) 2311cb0ef41Sopenharmony_ci// connect(port, [host], [cb]) 2321cb0ef41Sopenharmony_ci// connect(path, [cb]); 2331cb0ef41Sopenharmony_ci// 2341cb0ef41Sopenharmony_cifunction connect(...args) { 2351cb0ef41Sopenharmony_ci const normalized = normalizeArgs(args); 2361cb0ef41Sopenharmony_ci const options = normalized[0]; 2371cb0ef41Sopenharmony_ci debug('createConnection', normalized); 2381cb0ef41Sopenharmony_ci const socket = new Socket(options); 2391cb0ef41Sopenharmony_ci lazyChannels(); 2401cb0ef41Sopenharmony_ci if (netClientSocketChannel.hasSubscribers) { 2411cb0ef41Sopenharmony_ci netClientSocketChannel.publish({ 2421cb0ef41Sopenharmony_ci socket, 2431cb0ef41Sopenharmony_ci }); 2441cb0ef41Sopenharmony_ci } 2451cb0ef41Sopenharmony_ci if (options.timeout) { 2461cb0ef41Sopenharmony_ci socket.setTimeout(options.timeout); 2471cb0ef41Sopenharmony_ci } 2481cb0ef41Sopenharmony_ci 2491cb0ef41Sopenharmony_ci return socket.connect(normalized); 2501cb0ef41Sopenharmony_ci} 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_cifunction getDefaultAutoSelectFamily() { 2531cb0ef41Sopenharmony_ci return autoSelectFamilyDefault; 2541cb0ef41Sopenharmony_ci} 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_cifunction setDefaultAutoSelectFamily(value) { 2571cb0ef41Sopenharmony_ci validateBoolean(value, 'value'); 2581cb0ef41Sopenharmony_ci autoSelectFamilyDefault = value; 2591cb0ef41Sopenharmony_ci} 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_cifunction getDefaultAutoSelectFamilyAttemptTimeout() { 2621cb0ef41Sopenharmony_ci return autoSelectFamilyAttemptTimeoutDefault; 2631cb0ef41Sopenharmony_ci} 2641cb0ef41Sopenharmony_ci 2651cb0ef41Sopenharmony_cifunction setDefaultAutoSelectFamilyAttemptTimeout(value) { 2661cb0ef41Sopenharmony_ci validateInt32(value, 'value', 1); 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci if (value < 10) { 2691cb0ef41Sopenharmony_ci value = 10; 2701cb0ef41Sopenharmony_ci } 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci autoSelectFamilyAttemptTimeoutDefault = value; 2731cb0ef41Sopenharmony_ci} 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci// Returns an array [options, cb], where options is an object, 2761cb0ef41Sopenharmony_ci// cb is either a function or null. 2771cb0ef41Sopenharmony_ci// Used to normalize arguments of Socket.prototype.connect() and 2781cb0ef41Sopenharmony_ci// Server.prototype.listen(). Possible combinations of parameters: 2791cb0ef41Sopenharmony_ci// (options[...][, cb]) 2801cb0ef41Sopenharmony_ci// (path[...][, cb]) 2811cb0ef41Sopenharmony_ci// ([port][, host][...][, cb]) 2821cb0ef41Sopenharmony_ci// For Socket.prototype.connect(), the [...] part is ignored 2831cb0ef41Sopenharmony_ci// For Server.prototype.listen(), the [...] part is [, backlog] 2841cb0ef41Sopenharmony_ci// but will not be handled here (handled in listen()) 2851cb0ef41Sopenharmony_cifunction normalizeArgs(args) { 2861cb0ef41Sopenharmony_ci let arr; 2871cb0ef41Sopenharmony_ci 2881cb0ef41Sopenharmony_ci if (args.length === 0) { 2891cb0ef41Sopenharmony_ci arr = [{}, null]; 2901cb0ef41Sopenharmony_ci arr[normalizedArgsSymbol] = true; 2911cb0ef41Sopenharmony_ci return arr; 2921cb0ef41Sopenharmony_ci } 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_ci const arg0 = args[0]; 2951cb0ef41Sopenharmony_ci let options = {}; 2961cb0ef41Sopenharmony_ci if (typeof arg0 === 'object' && arg0 !== null) { 2971cb0ef41Sopenharmony_ci // (options[...][, cb]) 2981cb0ef41Sopenharmony_ci options = arg0; 2991cb0ef41Sopenharmony_ci } else if (isPipeName(arg0)) { 3001cb0ef41Sopenharmony_ci // (path[...][, cb]) 3011cb0ef41Sopenharmony_ci options.path = arg0; 3021cb0ef41Sopenharmony_ci } else { 3031cb0ef41Sopenharmony_ci // ([port][, host][...][, cb]) 3041cb0ef41Sopenharmony_ci options.port = arg0; 3051cb0ef41Sopenharmony_ci if (args.length > 1 && typeof args[1] === 'string') { 3061cb0ef41Sopenharmony_ci options.host = args[1]; 3071cb0ef41Sopenharmony_ci } 3081cb0ef41Sopenharmony_ci } 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_ci const cb = args[args.length - 1]; 3111cb0ef41Sopenharmony_ci if (typeof cb !== 'function') 3121cb0ef41Sopenharmony_ci arr = [options, null]; 3131cb0ef41Sopenharmony_ci else 3141cb0ef41Sopenharmony_ci arr = [options, cb]; 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_ci arr[normalizedArgsSymbol] = true; 3171cb0ef41Sopenharmony_ci return arr; 3181cb0ef41Sopenharmony_ci} 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci// Called when creating new Socket, or when re-using a closed Socket 3221cb0ef41Sopenharmony_cifunction initSocketHandle(self) { 3231cb0ef41Sopenharmony_ci self._undestroy(); 3241cb0ef41Sopenharmony_ci self._sockname = null; 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci // Handle creation may be deferred to bind() or connect() time. 3271cb0ef41Sopenharmony_ci if (self._handle) { 3281cb0ef41Sopenharmony_ci self._handle[owner_symbol] = self; 3291cb0ef41Sopenharmony_ci self._handle.onread = onStreamRead; 3301cb0ef41Sopenharmony_ci self[async_id_symbol] = getNewAsyncId(self._handle); 3311cb0ef41Sopenharmony_ci 3321cb0ef41Sopenharmony_ci let userBuf = self[kBuffer]; 3331cb0ef41Sopenharmony_ci if (userBuf) { 3341cb0ef41Sopenharmony_ci const bufGen = self[kBufferGen]; 3351cb0ef41Sopenharmony_ci if (bufGen !== null) { 3361cb0ef41Sopenharmony_ci userBuf = bufGen(); 3371cb0ef41Sopenharmony_ci if (!isUint8Array(userBuf)) 3381cb0ef41Sopenharmony_ci return; 3391cb0ef41Sopenharmony_ci self[kBuffer] = userBuf; 3401cb0ef41Sopenharmony_ci } 3411cb0ef41Sopenharmony_ci self._handle.useUserBuffer(userBuf); 3421cb0ef41Sopenharmony_ci } 3431cb0ef41Sopenharmony_ci } 3441cb0ef41Sopenharmony_ci} 3451cb0ef41Sopenharmony_ci 3461cb0ef41Sopenharmony_cifunction closeSocketHandle(self, isException, isCleanupPending = false) { 3471cb0ef41Sopenharmony_ci if (self._handle) { 3481cb0ef41Sopenharmony_ci self._handle.close(() => { 3491cb0ef41Sopenharmony_ci debug('emit close'); 3501cb0ef41Sopenharmony_ci self.emit('close', isException); 3511cb0ef41Sopenharmony_ci if (isCleanupPending) { 3521cb0ef41Sopenharmony_ci self._handle.onread = noop; 3531cb0ef41Sopenharmony_ci self._handle = null; 3541cb0ef41Sopenharmony_ci self._sockname = null; 3551cb0ef41Sopenharmony_ci } 3561cb0ef41Sopenharmony_ci }); 3571cb0ef41Sopenharmony_ci } 3581cb0ef41Sopenharmony_ci} 3591cb0ef41Sopenharmony_ci 3601cb0ef41Sopenharmony_ciconst kBytesRead = Symbol('kBytesRead'); 3611cb0ef41Sopenharmony_ciconst kBytesWritten = Symbol('kBytesWritten'); 3621cb0ef41Sopenharmony_ciconst kSetNoDelay = Symbol('kSetNoDelay'); 3631cb0ef41Sopenharmony_ciconst kSetKeepAlive = Symbol('kSetKeepAlive'); 3641cb0ef41Sopenharmony_ciconst kSetKeepAliveInitialDelay = Symbol('kSetKeepAliveInitialDelay'); 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_cifunction Socket(options) { 3671cb0ef41Sopenharmony_ci if (!(this instanceof Socket)) return new Socket(options); 3681cb0ef41Sopenharmony_ci if (options?.objectMode) { 3691cb0ef41Sopenharmony_ci throw new ERR_INVALID_ARG_VALUE( 3701cb0ef41Sopenharmony_ci 'options.objectMode', 3711cb0ef41Sopenharmony_ci options.objectMode, 3721cb0ef41Sopenharmony_ci 'is not supported', 3731cb0ef41Sopenharmony_ci ); 3741cb0ef41Sopenharmony_ci } else if (options?.readableObjectMode || options?.writableObjectMode) { 3751cb0ef41Sopenharmony_ci throw new ERR_INVALID_ARG_VALUE( 3761cb0ef41Sopenharmony_ci `options.${ 3771cb0ef41Sopenharmony_ci options.readableObjectMode ? 'readableObjectMode' : 'writableObjectMode' 3781cb0ef41Sopenharmony_ci }`, 3791cb0ef41Sopenharmony_ci options.readableObjectMode || options.writableObjectMode, 3801cb0ef41Sopenharmony_ci 'is not supported', 3811cb0ef41Sopenharmony_ci ); 3821cb0ef41Sopenharmony_ci } 3831cb0ef41Sopenharmony_ci if (typeof options?.keepAliveInitialDelay !== 'undefined') { 3841cb0ef41Sopenharmony_ci validateNumber( 3851cb0ef41Sopenharmony_ci options?.keepAliveInitialDelay, 'options.keepAliveInitialDelay', 3861cb0ef41Sopenharmony_ci ); 3871cb0ef41Sopenharmony_ci 3881cb0ef41Sopenharmony_ci if (options.keepAliveInitialDelay < 0) { 3891cb0ef41Sopenharmony_ci options.keepAliveInitialDelay = 0; 3901cb0ef41Sopenharmony_ci } 3911cb0ef41Sopenharmony_ci } 3921cb0ef41Sopenharmony_ci 3931cb0ef41Sopenharmony_ci this.connecting = false; 3941cb0ef41Sopenharmony_ci // Problem with this is that users can supply their own handle, that may not 3951cb0ef41Sopenharmony_ci // have _handle.getAsyncId(). In this case an[async_id_symbol] should 3961cb0ef41Sopenharmony_ci // probably be supplied by async_hooks. 3971cb0ef41Sopenharmony_ci this[async_id_symbol] = -1; 3981cb0ef41Sopenharmony_ci this._hadError = false; 3991cb0ef41Sopenharmony_ci this[kHandle] = null; 4001cb0ef41Sopenharmony_ci this._parent = null; 4011cb0ef41Sopenharmony_ci this._host = null; 4021cb0ef41Sopenharmony_ci this[kLastWriteQueueSize] = 0; 4031cb0ef41Sopenharmony_ci this[kTimeout] = null; 4041cb0ef41Sopenharmony_ci this[kBuffer] = null; 4051cb0ef41Sopenharmony_ci this[kBufferCb] = null; 4061cb0ef41Sopenharmony_ci this[kBufferGen] = null; 4071cb0ef41Sopenharmony_ci this._closeAfterHandlingError = false; 4081cb0ef41Sopenharmony_ci 4091cb0ef41Sopenharmony_ci if (typeof options === 'number') 4101cb0ef41Sopenharmony_ci options = { fd: options }; // Legacy interface. 4111cb0ef41Sopenharmony_ci else 4121cb0ef41Sopenharmony_ci options = { ...options }; 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_ci // Default to *not* allowing half open sockets. 4151cb0ef41Sopenharmony_ci options.allowHalfOpen = Boolean(options.allowHalfOpen); 4161cb0ef41Sopenharmony_ci // For backwards compat do not emit close on destroy. 4171cb0ef41Sopenharmony_ci options.emitClose = false; 4181cb0ef41Sopenharmony_ci options.autoDestroy = true; 4191cb0ef41Sopenharmony_ci // Handle strings directly. 4201cb0ef41Sopenharmony_ci options.decodeStrings = false; 4211cb0ef41Sopenharmony_ci stream.Duplex.call(this, options); 4221cb0ef41Sopenharmony_ci 4231cb0ef41Sopenharmony_ci if (options.handle) { 4241cb0ef41Sopenharmony_ci this._handle = options.handle; // private 4251cb0ef41Sopenharmony_ci this[async_id_symbol] = getNewAsyncId(this._handle); 4261cb0ef41Sopenharmony_ci } else if (options.fd !== undefined) { 4271cb0ef41Sopenharmony_ci const { fd } = options; 4281cb0ef41Sopenharmony_ci let err; 4291cb0ef41Sopenharmony_ci 4301cb0ef41Sopenharmony_ci // createHandle will throw ERR_INVALID_FD_TYPE if `fd` is not 4311cb0ef41Sopenharmony_ci // a valid `PIPE` or `TCP` descriptor 4321cb0ef41Sopenharmony_ci this._handle = createHandle(fd, false); 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_ci err = this._handle.open(fd); 4351cb0ef41Sopenharmony_ci 4361cb0ef41Sopenharmony_ci // While difficult to fabricate, in some architectures 4371cb0ef41Sopenharmony_ci // `open` may return an error code for valid file descriptors 4381cb0ef41Sopenharmony_ci // which cannot be opened. This is difficult to test as most 4391cb0ef41Sopenharmony_ci // un-openable fds will throw on `createHandle` 4401cb0ef41Sopenharmony_ci if (err) 4411cb0ef41Sopenharmony_ci throw errnoException(err, 'open'); 4421cb0ef41Sopenharmony_ci 4431cb0ef41Sopenharmony_ci this[async_id_symbol] = this._handle.getAsyncId(); 4441cb0ef41Sopenharmony_ci 4451cb0ef41Sopenharmony_ci if ((fd === 1 || fd === 2) && 4461cb0ef41Sopenharmony_ci (this._handle instanceof Pipe) && isWindows) { 4471cb0ef41Sopenharmony_ci // Make stdout and stderr blocking on Windows 4481cb0ef41Sopenharmony_ci err = this._handle.setBlocking(true); 4491cb0ef41Sopenharmony_ci if (err) 4501cb0ef41Sopenharmony_ci throw errnoException(err, 'setBlocking'); 4511cb0ef41Sopenharmony_ci 4521cb0ef41Sopenharmony_ci this._writev = null; 4531cb0ef41Sopenharmony_ci this._write = makeSyncWrite(fd); 4541cb0ef41Sopenharmony_ci // makeSyncWrite adjusts this value like the original handle would, so 4551cb0ef41Sopenharmony_ci // we need to let it do that by turning it into a writable, own 4561cb0ef41Sopenharmony_ci // property. 4571cb0ef41Sopenharmony_ci ObjectDefineProperty(this._handle, 'bytesWritten', { 4581cb0ef41Sopenharmony_ci __proto__: null, 4591cb0ef41Sopenharmony_ci value: 0, writable: true, 4601cb0ef41Sopenharmony_ci }); 4611cb0ef41Sopenharmony_ci } 4621cb0ef41Sopenharmony_ci } 4631cb0ef41Sopenharmony_ci 4641cb0ef41Sopenharmony_ci const onread = options.onread; 4651cb0ef41Sopenharmony_ci if (onread !== null && typeof onread === 'object' && 4661cb0ef41Sopenharmony_ci (isUint8Array(onread.buffer) || typeof onread.buffer === 'function') && 4671cb0ef41Sopenharmony_ci typeof onread.callback === 'function') { 4681cb0ef41Sopenharmony_ci if (typeof onread.buffer === 'function') { 4691cb0ef41Sopenharmony_ci this[kBuffer] = true; 4701cb0ef41Sopenharmony_ci this[kBufferGen] = onread.buffer; 4711cb0ef41Sopenharmony_ci } else { 4721cb0ef41Sopenharmony_ci this[kBuffer] = onread.buffer; 4731cb0ef41Sopenharmony_ci } 4741cb0ef41Sopenharmony_ci this[kBufferCb] = onread.callback; 4751cb0ef41Sopenharmony_ci } 4761cb0ef41Sopenharmony_ci 4771cb0ef41Sopenharmony_ci this[kSetNoDelay] = Boolean(options.noDelay); 4781cb0ef41Sopenharmony_ci this[kSetKeepAlive] = Boolean(options.keepAlive); 4791cb0ef41Sopenharmony_ci this[kSetKeepAliveInitialDelay] = ~~(options.keepAliveInitialDelay / 1000); 4801cb0ef41Sopenharmony_ci 4811cb0ef41Sopenharmony_ci // Shut down the socket when we're finished with it. 4821cb0ef41Sopenharmony_ci this.on('end', onReadableStreamEnd); 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci initSocketHandle(this); 4851cb0ef41Sopenharmony_ci 4861cb0ef41Sopenharmony_ci this._pendingData = null; 4871cb0ef41Sopenharmony_ci this._pendingEncoding = ''; 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_ci // If we have a handle, then start the flow of data into the 4901cb0ef41Sopenharmony_ci // buffer. if not, then this will happen when we connect 4911cb0ef41Sopenharmony_ci if (this._handle && options.readable !== false) { 4921cb0ef41Sopenharmony_ci if (options.pauseOnCreate) { 4931cb0ef41Sopenharmony_ci // Stop the handle from reading and pause the stream 4941cb0ef41Sopenharmony_ci this._handle.reading = false; 4951cb0ef41Sopenharmony_ci this._handle.readStop(); 4961cb0ef41Sopenharmony_ci this.readableFlowing = false; 4971cb0ef41Sopenharmony_ci } else if (!options.manualStart) { 4981cb0ef41Sopenharmony_ci this.read(0); 4991cb0ef41Sopenharmony_ci } 5001cb0ef41Sopenharmony_ci } 5011cb0ef41Sopenharmony_ci 5021cb0ef41Sopenharmony_ci // Reserve properties 5031cb0ef41Sopenharmony_ci this.server = null; 5041cb0ef41Sopenharmony_ci this._server = null; 5051cb0ef41Sopenharmony_ci 5061cb0ef41Sopenharmony_ci // Used after `.destroy()` 5071cb0ef41Sopenharmony_ci this[kBytesRead] = 0; 5081cb0ef41Sopenharmony_ci this[kBytesWritten] = 0; 5091cb0ef41Sopenharmony_ci} 5101cb0ef41Sopenharmony_ciObjectSetPrototypeOf(Socket.prototype, stream.Duplex.prototype); 5111cb0ef41Sopenharmony_ciObjectSetPrototypeOf(Socket, stream.Duplex); 5121cb0ef41Sopenharmony_ci 5131cb0ef41Sopenharmony_ci// Refresh existing timeouts. 5141cb0ef41Sopenharmony_ciSocket.prototype._unrefTimer = function _unrefTimer() { 5151cb0ef41Sopenharmony_ci for (let s = this; s !== null; s = s._parent) { 5161cb0ef41Sopenharmony_ci if (s[kTimeout]) 5171cb0ef41Sopenharmony_ci s[kTimeout].refresh(); 5181cb0ef41Sopenharmony_ci } 5191cb0ef41Sopenharmony_ci}; 5201cb0ef41Sopenharmony_ci 5211cb0ef41Sopenharmony_ci 5221cb0ef41Sopenharmony_ci// The user has called .end(), and all the bytes have been 5231cb0ef41Sopenharmony_ci// sent out to the other side. 5241cb0ef41Sopenharmony_ciSocket.prototype._final = function(cb) { 5251cb0ef41Sopenharmony_ci // If still connecting - defer handling `_final` until 'connect' will happen 5261cb0ef41Sopenharmony_ci if (this.pending) { 5271cb0ef41Sopenharmony_ci debug('_final: not yet connected'); 5281cb0ef41Sopenharmony_ci return this.once('connect', () => this._final(cb)); 5291cb0ef41Sopenharmony_ci } 5301cb0ef41Sopenharmony_ci 5311cb0ef41Sopenharmony_ci if (!this._handle) 5321cb0ef41Sopenharmony_ci return cb(); 5331cb0ef41Sopenharmony_ci 5341cb0ef41Sopenharmony_ci debug('_final: not ended, call shutdown()'); 5351cb0ef41Sopenharmony_ci 5361cb0ef41Sopenharmony_ci const req = new ShutdownWrap(); 5371cb0ef41Sopenharmony_ci req.oncomplete = afterShutdown; 5381cb0ef41Sopenharmony_ci req.handle = this._handle; 5391cb0ef41Sopenharmony_ci req.callback = cb; 5401cb0ef41Sopenharmony_ci const err = this._handle.shutdown(req); 5411cb0ef41Sopenharmony_ci 5421cb0ef41Sopenharmony_ci if (err === 1 || err === UV_ENOTCONN) // synchronous finish 5431cb0ef41Sopenharmony_ci return cb(); 5441cb0ef41Sopenharmony_ci else if (err !== 0) 5451cb0ef41Sopenharmony_ci return cb(errnoException(err, 'shutdown')); 5461cb0ef41Sopenharmony_ci}; 5471cb0ef41Sopenharmony_ci 5481cb0ef41Sopenharmony_cifunction afterShutdown() { 5491cb0ef41Sopenharmony_ci const self = this.handle[owner_symbol]; 5501cb0ef41Sopenharmony_ci 5511cb0ef41Sopenharmony_ci debug('afterShutdown destroyed=%j', self.destroyed); 5521cb0ef41Sopenharmony_ci 5531cb0ef41Sopenharmony_ci this.callback(); 5541cb0ef41Sopenharmony_ci} 5551cb0ef41Sopenharmony_ci 5561cb0ef41Sopenharmony_ci// Provide a better error message when we call end() as a result 5571cb0ef41Sopenharmony_ci// of the other side sending a FIN. The standard 'write after end' 5581cb0ef41Sopenharmony_ci// is overly vague, and makes it seem like the user's code is to blame. 5591cb0ef41Sopenharmony_cifunction writeAfterFIN(chunk, encoding, cb) { 5601cb0ef41Sopenharmony_ci if (!this.writableEnded) { 5611cb0ef41Sopenharmony_ci return stream.Duplex.prototype.write.call(this, chunk, encoding, cb); 5621cb0ef41Sopenharmony_ci } 5631cb0ef41Sopenharmony_ci 5641cb0ef41Sopenharmony_ci if (typeof encoding === 'function') { 5651cb0ef41Sopenharmony_ci cb = encoding; 5661cb0ef41Sopenharmony_ci encoding = null; 5671cb0ef41Sopenharmony_ci } 5681cb0ef41Sopenharmony_ci 5691cb0ef41Sopenharmony_ci const er = genericNodeError( 5701cb0ef41Sopenharmony_ci 'This socket has been ended by the other party', 5711cb0ef41Sopenharmony_ci { code: 'EPIPE' }, 5721cb0ef41Sopenharmony_ci ); 5731cb0ef41Sopenharmony_ci if (typeof cb === 'function') { 5741cb0ef41Sopenharmony_ci defaultTriggerAsyncIdScope(this[async_id_symbol], process.nextTick, cb, er); 5751cb0ef41Sopenharmony_ci } 5761cb0ef41Sopenharmony_ci this.destroy(er); 5771cb0ef41Sopenharmony_ci 5781cb0ef41Sopenharmony_ci return false; 5791cb0ef41Sopenharmony_ci} 5801cb0ef41Sopenharmony_ci 5811cb0ef41Sopenharmony_ciSocket.prototype.setTimeout = setStreamTimeout; 5821cb0ef41Sopenharmony_ci 5831cb0ef41Sopenharmony_ci 5841cb0ef41Sopenharmony_ciSocket.prototype._onTimeout = function() { 5851cb0ef41Sopenharmony_ci const handle = this._handle; 5861cb0ef41Sopenharmony_ci const lastWriteQueueSize = this[kLastWriteQueueSize]; 5871cb0ef41Sopenharmony_ci if (lastWriteQueueSize > 0 && handle) { 5881cb0ef41Sopenharmony_ci // `lastWriteQueueSize !== writeQueueSize` means there is 5891cb0ef41Sopenharmony_ci // an active write in progress, so we suppress the timeout. 5901cb0ef41Sopenharmony_ci const { writeQueueSize } = handle; 5911cb0ef41Sopenharmony_ci if (lastWriteQueueSize !== writeQueueSize) { 5921cb0ef41Sopenharmony_ci this[kLastWriteQueueSize] = writeQueueSize; 5931cb0ef41Sopenharmony_ci this._unrefTimer(); 5941cb0ef41Sopenharmony_ci return; 5951cb0ef41Sopenharmony_ci } 5961cb0ef41Sopenharmony_ci } 5971cb0ef41Sopenharmony_ci debug('_onTimeout'); 5981cb0ef41Sopenharmony_ci this.emit('timeout'); 5991cb0ef41Sopenharmony_ci}; 6001cb0ef41Sopenharmony_ci 6011cb0ef41Sopenharmony_ci 6021cb0ef41Sopenharmony_ciSocket.prototype.setNoDelay = function(enable) { 6031cb0ef41Sopenharmony_ci // Backwards compatibility: assume true when `enable` is omitted 6041cb0ef41Sopenharmony_ci enable = Boolean(enable === undefined ? true : enable); 6051cb0ef41Sopenharmony_ci 6061cb0ef41Sopenharmony_ci if (!this._handle) { 6071cb0ef41Sopenharmony_ci this[kSetNoDelay] = enable; 6081cb0ef41Sopenharmony_ci return this; 6091cb0ef41Sopenharmony_ci } 6101cb0ef41Sopenharmony_ci 6111cb0ef41Sopenharmony_ci if (this._handle.setNoDelay && enable !== this[kSetNoDelay]) { 6121cb0ef41Sopenharmony_ci this[kSetNoDelay] = enable; 6131cb0ef41Sopenharmony_ci this._handle.setNoDelay(enable); 6141cb0ef41Sopenharmony_ci } 6151cb0ef41Sopenharmony_ci 6161cb0ef41Sopenharmony_ci return this; 6171cb0ef41Sopenharmony_ci}; 6181cb0ef41Sopenharmony_ci 6191cb0ef41Sopenharmony_ci 6201cb0ef41Sopenharmony_ciSocket.prototype.setKeepAlive = function(enable, initialDelayMsecs) { 6211cb0ef41Sopenharmony_ci enable = Boolean(enable); 6221cb0ef41Sopenharmony_ci const initialDelay = ~~(initialDelayMsecs / 1000); 6231cb0ef41Sopenharmony_ci 6241cb0ef41Sopenharmony_ci if (!this._handle) { 6251cb0ef41Sopenharmony_ci this[kSetKeepAlive] = enable; 6261cb0ef41Sopenharmony_ci this[kSetKeepAliveInitialDelay] = initialDelay; 6271cb0ef41Sopenharmony_ci return this; 6281cb0ef41Sopenharmony_ci } 6291cb0ef41Sopenharmony_ci 6301cb0ef41Sopenharmony_ci if (!this._handle.setKeepAlive) { 6311cb0ef41Sopenharmony_ci return this; 6321cb0ef41Sopenharmony_ci } 6331cb0ef41Sopenharmony_ci 6341cb0ef41Sopenharmony_ci if (enable !== this[kSetKeepAlive] || 6351cb0ef41Sopenharmony_ci ( 6361cb0ef41Sopenharmony_ci enable && 6371cb0ef41Sopenharmony_ci this[kSetKeepAliveInitialDelay] !== initialDelay 6381cb0ef41Sopenharmony_ci ) 6391cb0ef41Sopenharmony_ci ) { 6401cb0ef41Sopenharmony_ci this[kSetKeepAlive] = enable; 6411cb0ef41Sopenharmony_ci this[kSetKeepAliveInitialDelay] = initialDelay; 6421cb0ef41Sopenharmony_ci this._handle.setKeepAlive(enable, initialDelay); 6431cb0ef41Sopenharmony_ci } 6441cb0ef41Sopenharmony_ci 6451cb0ef41Sopenharmony_ci return this; 6461cb0ef41Sopenharmony_ci}; 6471cb0ef41Sopenharmony_ci 6481cb0ef41Sopenharmony_ci 6491cb0ef41Sopenharmony_ciSocket.prototype.address = function() { 6501cb0ef41Sopenharmony_ci return this._getsockname(); 6511cb0ef41Sopenharmony_ci}; 6521cb0ef41Sopenharmony_ci 6531cb0ef41Sopenharmony_ci 6541cb0ef41Sopenharmony_ciObjectDefineProperty(Socket.prototype, '_connecting', { 6551cb0ef41Sopenharmony_ci __proto__: null, 6561cb0ef41Sopenharmony_ci get: function() { 6571cb0ef41Sopenharmony_ci return this.connecting; 6581cb0ef41Sopenharmony_ci }, 6591cb0ef41Sopenharmony_ci}); 6601cb0ef41Sopenharmony_ci 6611cb0ef41Sopenharmony_ciObjectDefineProperty(Socket.prototype, 'pending', { 6621cb0ef41Sopenharmony_ci __proto__: null, 6631cb0ef41Sopenharmony_ci get() { 6641cb0ef41Sopenharmony_ci return !this._handle || this.connecting; 6651cb0ef41Sopenharmony_ci }, 6661cb0ef41Sopenharmony_ci configurable: true, 6671cb0ef41Sopenharmony_ci}); 6681cb0ef41Sopenharmony_ci 6691cb0ef41Sopenharmony_ci 6701cb0ef41Sopenharmony_ciObjectDefineProperty(Socket.prototype, 'readyState', { 6711cb0ef41Sopenharmony_ci __proto__: null, 6721cb0ef41Sopenharmony_ci get: function() { 6731cb0ef41Sopenharmony_ci if (this.connecting) { 6741cb0ef41Sopenharmony_ci return 'opening'; 6751cb0ef41Sopenharmony_ci } else if (this.readable && this.writable) { 6761cb0ef41Sopenharmony_ci return 'open'; 6771cb0ef41Sopenharmony_ci } else if (this.readable && !this.writable) { 6781cb0ef41Sopenharmony_ci return 'readOnly'; 6791cb0ef41Sopenharmony_ci } else if (!this.readable && this.writable) { 6801cb0ef41Sopenharmony_ci return 'writeOnly'; 6811cb0ef41Sopenharmony_ci } 6821cb0ef41Sopenharmony_ci return 'closed'; 6831cb0ef41Sopenharmony_ci }, 6841cb0ef41Sopenharmony_ci}); 6851cb0ef41Sopenharmony_ci 6861cb0ef41Sopenharmony_ci 6871cb0ef41Sopenharmony_ciObjectDefineProperty(Socket.prototype, 'bufferSize', { 6881cb0ef41Sopenharmony_ci __proto__: null, 6891cb0ef41Sopenharmony_ci get: function() { 6901cb0ef41Sopenharmony_ci if (this._handle) { 6911cb0ef41Sopenharmony_ci return this.writableLength; 6921cb0ef41Sopenharmony_ci } 6931cb0ef41Sopenharmony_ci }, 6941cb0ef41Sopenharmony_ci}); 6951cb0ef41Sopenharmony_ci 6961cb0ef41Sopenharmony_ciObjectDefineProperty(Socket.prototype, kUpdateTimer, { 6971cb0ef41Sopenharmony_ci __proto__: null, 6981cb0ef41Sopenharmony_ci get: function() { 6991cb0ef41Sopenharmony_ci return this._unrefTimer; 7001cb0ef41Sopenharmony_ci }, 7011cb0ef41Sopenharmony_ci}); 7021cb0ef41Sopenharmony_ci 7031cb0ef41Sopenharmony_ci 7041cb0ef41Sopenharmony_cifunction tryReadStart(socket) { 7051cb0ef41Sopenharmony_ci // Not already reading, start the flow 7061cb0ef41Sopenharmony_ci debug('Socket._handle.readStart'); 7071cb0ef41Sopenharmony_ci socket._handle.reading = true; 7081cb0ef41Sopenharmony_ci const err = socket._handle.readStart(); 7091cb0ef41Sopenharmony_ci if (err) 7101cb0ef41Sopenharmony_ci socket.destroy(errnoException(err, 'read')); 7111cb0ef41Sopenharmony_ci} 7121cb0ef41Sopenharmony_ci 7131cb0ef41Sopenharmony_ci// Just call handle.readStart until we have enough in the buffer 7141cb0ef41Sopenharmony_ciSocket.prototype._read = function(n) { 7151cb0ef41Sopenharmony_ci debug( 7161cb0ef41Sopenharmony_ci '_read - n', n, 7171cb0ef41Sopenharmony_ci 'isConnecting?', !!this.connecting, 7181cb0ef41Sopenharmony_ci 'hasHandle?', !!this._handle, 7191cb0ef41Sopenharmony_ci ); 7201cb0ef41Sopenharmony_ci 7211cb0ef41Sopenharmony_ci if (this.connecting || !this._handle) { 7221cb0ef41Sopenharmony_ci debug('_read wait for connection'); 7231cb0ef41Sopenharmony_ci this.once('connect', () => this._read(n)); 7241cb0ef41Sopenharmony_ci } else if (!this._handle.reading) { 7251cb0ef41Sopenharmony_ci tryReadStart(this); 7261cb0ef41Sopenharmony_ci } 7271cb0ef41Sopenharmony_ci}; 7281cb0ef41Sopenharmony_ci 7291cb0ef41Sopenharmony_ci 7301cb0ef41Sopenharmony_ciSocket.prototype.end = function(data, encoding, callback) { 7311cb0ef41Sopenharmony_ci stream.Duplex.prototype.end.call(this, 7321cb0ef41Sopenharmony_ci data, encoding, callback); 7331cb0ef41Sopenharmony_ci DTRACE_NET_STREAM_END(this); 7341cb0ef41Sopenharmony_ci return this; 7351cb0ef41Sopenharmony_ci}; 7361cb0ef41Sopenharmony_ci 7371cb0ef41Sopenharmony_ciSocket.prototype.resetAndDestroy = function() { 7381cb0ef41Sopenharmony_ci if (this._handle) { 7391cb0ef41Sopenharmony_ci if (!(this._handle instanceof TCP)) 7401cb0ef41Sopenharmony_ci throw new ERR_INVALID_HANDLE_TYPE(); 7411cb0ef41Sopenharmony_ci if (this.connecting) { 7421cb0ef41Sopenharmony_ci debug('reset wait for connection'); 7431cb0ef41Sopenharmony_ci this.once('connect', () => this._reset()); 7441cb0ef41Sopenharmony_ci } else { 7451cb0ef41Sopenharmony_ci this._reset(); 7461cb0ef41Sopenharmony_ci } 7471cb0ef41Sopenharmony_ci } else { 7481cb0ef41Sopenharmony_ci this.destroy(new ERR_SOCKET_CLOSED()); 7491cb0ef41Sopenharmony_ci } 7501cb0ef41Sopenharmony_ci return this; 7511cb0ef41Sopenharmony_ci}; 7521cb0ef41Sopenharmony_ci 7531cb0ef41Sopenharmony_ciSocket.prototype.pause = function() { 7541cb0ef41Sopenharmony_ci if (this[kBuffer] && !this.connecting && this._handle && 7551cb0ef41Sopenharmony_ci this._handle.reading) { 7561cb0ef41Sopenharmony_ci this._handle.reading = false; 7571cb0ef41Sopenharmony_ci if (!this.destroyed) { 7581cb0ef41Sopenharmony_ci const err = this._handle.readStop(); 7591cb0ef41Sopenharmony_ci if (err) 7601cb0ef41Sopenharmony_ci this.destroy(errnoException(err, 'read')); 7611cb0ef41Sopenharmony_ci } 7621cb0ef41Sopenharmony_ci } 7631cb0ef41Sopenharmony_ci return stream.Duplex.prototype.pause.call(this); 7641cb0ef41Sopenharmony_ci}; 7651cb0ef41Sopenharmony_ci 7661cb0ef41Sopenharmony_ci 7671cb0ef41Sopenharmony_ciSocket.prototype.resume = function() { 7681cb0ef41Sopenharmony_ci if (this[kBuffer] && !this.connecting && this._handle && 7691cb0ef41Sopenharmony_ci !this._handle.reading) { 7701cb0ef41Sopenharmony_ci tryReadStart(this); 7711cb0ef41Sopenharmony_ci } 7721cb0ef41Sopenharmony_ci return stream.Duplex.prototype.resume.call(this); 7731cb0ef41Sopenharmony_ci}; 7741cb0ef41Sopenharmony_ci 7751cb0ef41Sopenharmony_ci 7761cb0ef41Sopenharmony_ciSocket.prototype.read = function(n) { 7771cb0ef41Sopenharmony_ci if (this[kBuffer] && !this.connecting && this._handle && 7781cb0ef41Sopenharmony_ci !this._handle.reading) { 7791cb0ef41Sopenharmony_ci tryReadStart(this); 7801cb0ef41Sopenharmony_ci } 7811cb0ef41Sopenharmony_ci return stream.Duplex.prototype.read.call(this, n); 7821cb0ef41Sopenharmony_ci}; 7831cb0ef41Sopenharmony_ci 7841cb0ef41Sopenharmony_ci 7851cb0ef41Sopenharmony_ci// Called when the 'end' event is emitted. 7861cb0ef41Sopenharmony_cifunction onReadableStreamEnd() { 7871cb0ef41Sopenharmony_ci if (!this.allowHalfOpen) { 7881cb0ef41Sopenharmony_ci this.write = writeAfterFIN; 7891cb0ef41Sopenharmony_ci } 7901cb0ef41Sopenharmony_ci} 7911cb0ef41Sopenharmony_ci 7921cb0ef41Sopenharmony_ci 7931cb0ef41Sopenharmony_ciSocket.prototype.destroySoon = function() { 7941cb0ef41Sopenharmony_ci if (this.writable) 7951cb0ef41Sopenharmony_ci this.end(); 7961cb0ef41Sopenharmony_ci 7971cb0ef41Sopenharmony_ci if (this.writableFinished) 7981cb0ef41Sopenharmony_ci this.destroy(); 7991cb0ef41Sopenharmony_ci else 8001cb0ef41Sopenharmony_ci this.once('finish', this.destroy); 8011cb0ef41Sopenharmony_ci}; 8021cb0ef41Sopenharmony_ci 8031cb0ef41Sopenharmony_ci 8041cb0ef41Sopenharmony_ciSocket.prototype._destroy = function(exception, cb) { 8051cb0ef41Sopenharmony_ci debug('destroy'); 8061cb0ef41Sopenharmony_ci 8071cb0ef41Sopenharmony_ci this.connecting = false; 8081cb0ef41Sopenharmony_ci 8091cb0ef41Sopenharmony_ci for (let s = this; s !== null; s = s._parent) { 8101cb0ef41Sopenharmony_ci clearTimeout(s[kTimeout]); 8111cb0ef41Sopenharmony_ci } 8121cb0ef41Sopenharmony_ci 8131cb0ef41Sopenharmony_ci debug('close'); 8141cb0ef41Sopenharmony_ci if (this._handle) { 8151cb0ef41Sopenharmony_ci if (this !== process.stderr) 8161cb0ef41Sopenharmony_ci debug('close handle'); 8171cb0ef41Sopenharmony_ci const isException = exception ? true : false; 8181cb0ef41Sopenharmony_ci // `bytesRead` and `kBytesWritten` should be accessible after `.destroy()` 8191cb0ef41Sopenharmony_ci this[kBytesRead] = this._handle.bytesRead; 8201cb0ef41Sopenharmony_ci this[kBytesWritten] = this._handle.bytesWritten; 8211cb0ef41Sopenharmony_ci 8221cb0ef41Sopenharmony_ci if (this.resetAndClosing) { 8231cb0ef41Sopenharmony_ci this.resetAndClosing = false; 8241cb0ef41Sopenharmony_ci const err = this._handle.reset(() => { 8251cb0ef41Sopenharmony_ci debug('emit close'); 8261cb0ef41Sopenharmony_ci this.emit('close', isException); 8271cb0ef41Sopenharmony_ci }); 8281cb0ef41Sopenharmony_ci if (err) 8291cb0ef41Sopenharmony_ci this.emit('error', errnoException(err, 'reset')); 8301cb0ef41Sopenharmony_ci } else if (this._closeAfterHandlingError) { 8311cb0ef41Sopenharmony_ci // Enqueue closing the socket as a microtask, so that the socket can be 8321cb0ef41Sopenharmony_ci // accessible when an `error` event is handled in the `next tick queue`. 8331cb0ef41Sopenharmony_ci queueMicrotask(() => closeSocketHandle(this, isException, true)); 8341cb0ef41Sopenharmony_ci } else { 8351cb0ef41Sopenharmony_ci closeSocketHandle(this, isException); 8361cb0ef41Sopenharmony_ci } 8371cb0ef41Sopenharmony_ci 8381cb0ef41Sopenharmony_ci if (!this._closeAfterHandlingError) { 8391cb0ef41Sopenharmony_ci this._handle.onread = noop; 8401cb0ef41Sopenharmony_ci this._handle = null; 8411cb0ef41Sopenharmony_ci this._sockname = null; 8421cb0ef41Sopenharmony_ci } 8431cb0ef41Sopenharmony_ci cb(exception); 8441cb0ef41Sopenharmony_ci } else { 8451cb0ef41Sopenharmony_ci cb(exception); 8461cb0ef41Sopenharmony_ci process.nextTick(emitCloseNT, this); 8471cb0ef41Sopenharmony_ci } 8481cb0ef41Sopenharmony_ci 8491cb0ef41Sopenharmony_ci if (this._server) { 8501cb0ef41Sopenharmony_ci debug('has server'); 8511cb0ef41Sopenharmony_ci this._server._connections--; 8521cb0ef41Sopenharmony_ci if (this._server._emitCloseIfDrained) { 8531cb0ef41Sopenharmony_ci this._server._emitCloseIfDrained(); 8541cb0ef41Sopenharmony_ci } 8551cb0ef41Sopenharmony_ci } 8561cb0ef41Sopenharmony_ci}; 8571cb0ef41Sopenharmony_ci 8581cb0ef41Sopenharmony_ciSocket.prototype._reset = function() { 8591cb0ef41Sopenharmony_ci debug('reset connection'); 8601cb0ef41Sopenharmony_ci this.resetAndClosing = true; 8611cb0ef41Sopenharmony_ci return this.destroy(); 8621cb0ef41Sopenharmony_ci}; 8631cb0ef41Sopenharmony_ci 8641cb0ef41Sopenharmony_ciSocket.prototype._getpeername = function() { 8651cb0ef41Sopenharmony_ci if (!this._handle || !this._handle.getpeername || this.connecting) { 8661cb0ef41Sopenharmony_ci return this._peername || {}; 8671cb0ef41Sopenharmony_ci } else if (!this._peername) { 8681cb0ef41Sopenharmony_ci const out = {}; 8691cb0ef41Sopenharmony_ci const err = this._handle.getpeername(out); 8701cb0ef41Sopenharmony_ci if (err) return out; 8711cb0ef41Sopenharmony_ci this._peername = out; 8721cb0ef41Sopenharmony_ci } 8731cb0ef41Sopenharmony_ci return this._peername; 8741cb0ef41Sopenharmony_ci}; 8751cb0ef41Sopenharmony_ci 8761cb0ef41Sopenharmony_cifunction protoGetter(name, callback) { 8771cb0ef41Sopenharmony_ci ObjectDefineProperty(Socket.prototype, name, { 8781cb0ef41Sopenharmony_ci __proto__: null, 8791cb0ef41Sopenharmony_ci configurable: false, 8801cb0ef41Sopenharmony_ci enumerable: true, 8811cb0ef41Sopenharmony_ci get: callback, 8821cb0ef41Sopenharmony_ci }); 8831cb0ef41Sopenharmony_ci} 8841cb0ef41Sopenharmony_ci 8851cb0ef41Sopenharmony_ciprotoGetter('bytesRead', function bytesRead() { 8861cb0ef41Sopenharmony_ci return this._handle ? this._handle.bytesRead : this[kBytesRead]; 8871cb0ef41Sopenharmony_ci}); 8881cb0ef41Sopenharmony_ci 8891cb0ef41Sopenharmony_ciprotoGetter('remoteAddress', function remoteAddress() { 8901cb0ef41Sopenharmony_ci return this._getpeername().address; 8911cb0ef41Sopenharmony_ci}); 8921cb0ef41Sopenharmony_ci 8931cb0ef41Sopenharmony_ciprotoGetter('remoteFamily', function remoteFamily() { 8941cb0ef41Sopenharmony_ci return this._getpeername().family; 8951cb0ef41Sopenharmony_ci}); 8961cb0ef41Sopenharmony_ci 8971cb0ef41Sopenharmony_ciprotoGetter('remotePort', function remotePort() { 8981cb0ef41Sopenharmony_ci return this._getpeername().port; 8991cb0ef41Sopenharmony_ci}); 9001cb0ef41Sopenharmony_ci 9011cb0ef41Sopenharmony_ci 9021cb0ef41Sopenharmony_ciSocket.prototype._getsockname = function() { 9031cb0ef41Sopenharmony_ci if (!this._handle || !this._handle.getsockname) { 9041cb0ef41Sopenharmony_ci return {}; 9051cb0ef41Sopenharmony_ci } else if (!this._sockname) { 9061cb0ef41Sopenharmony_ci this._sockname = {}; 9071cb0ef41Sopenharmony_ci // FIXME(bnoordhuis) Throw when the return value is not 0? 9081cb0ef41Sopenharmony_ci this._handle.getsockname(this._sockname); 9091cb0ef41Sopenharmony_ci } 9101cb0ef41Sopenharmony_ci return this._sockname; 9111cb0ef41Sopenharmony_ci}; 9121cb0ef41Sopenharmony_ci 9131cb0ef41Sopenharmony_ci 9141cb0ef41Sopenharmony_ciprotoGetter('localAddress', function localAddress() { 9151cb0ef41Sopenharmony_ci return this._getsockname().address; 9161cb0ef41Sopenharmony_ci}); 9171cb0ef41Sopenharmony_ci 9181cb0ef41Sopenharmony_ci 9191cb0ef41Sopenharmony_ciprotoGetter('localPort', function localPort() { 9201cb0ef41Sopenharmony_ci return this._getsockname().port; 9211cb0ef41Sopenharmony_ci}); 9221cb0ef41Sopenharmony_ci 9231cb0ef41Sopenharmony_ciprotoGetter('localFamily', function localFamily() { 9241cb0ef41Sopenharmony_ci return this._getsockname().family; 9251cb0ef41Sopenharmony_ci}); 9261cb0ef41Sopenharmony_ci 9271cb0ef41Sopenharmony_ciSocket.prototype[kAfterAsyncWrite] = function() { 9281cb0ef41Sopenharmony_ci this[kLastWriteQueueSize] = 0; 9291cb0ef41Sopenharmony_ci}; 9301cb0ef41Sopenharmony_ci 9311cb0ef41Sopenharmony_ciSocket.prototype._writeGeneric = function(writev, data, encoding, cb) { 9321cb0ef41Sopenharmony_ci // If we are still connecting, then buffer this for later. 9331cb0ef41Sopenharmony_ci // The Writable logic will buffer up any more writes while 9341cb0ef41Sopenharmony_ci // waiting for this one to be done. 9351cb0ef41Sopenharmony_ci if (this.connecting) { 9361cb0ef41Sopenharmony_ci this._pendingData = data; 9371cb0ef41Sopenharmony_ci this._pendingEncoding = encoding; 9381cb0ef41Sopenharmony_ci this.once('connect', function connect() { 9391cb0ef41Sopenharmony_ci this.off('close', onClose); 9401cb0ef41Sopenharmony_ci this._writeGeneric(writev, data, encoding, cb); 9411cb0ef41Sopenharmony_ci }); 9421cb0ef41Sopenharmony_ci function onClose() { 9431cb0ef41Sopenharmony_ci cb(new ERR_SOCKET_CLOSED_BEFORE_CONNECTION()); 9441cb0ef41Sopenharmony_ci } 9451cb0ef41Sopenharmony_ci this.once('close', onClose); 9461cb0ef41Sopenharmony_ci return; 9471cb0ef41Sopenharmony_ci } 9481cb0ef41Sopenharmony_ci this._pendingData = null; 9491cb0ef41Sopenharmony_ci this._pendingEncoding = ''; 9501cb0ef41Sopenharmony_ci 9511cb0ef41Sopenharmony_ci if (!this._handle) { 9521cb0ef41Sopenharmony_ci cb(new ERR_SOCKET_CLOSED()); 9531cb0ef41Sopenharmony_ci return false; 9541cb0ef41Sopenharmony_ci } 9551cb0ef41Sopenharmony_ci 9561cb0ef41Sopenharmony_ci this._unrefTimer(); 9571cb0ef41Sopenharmony_ci 9581cb0ef41Sopenharmony_ci let req; 9591cb0ef41Sopenharmony_ci if (writev) 9601cb0ef41Sopenharmony_ci req = writevGeneric(this, data, cb); 9611cb0ef41Sopenharmony_ci else 9621cb0ef41Sopenharmony_ci req = writeGeneric(this, data, encoding, cb); 9631cb0ef41Sopenharmony_ci if (req.async) 9641cb0ef41Sopenharmony_ci this[kLastWriteQueueSize] = req.bytes; 9651cb0ef41Sopenharmony_ci}; 9661cb0ef41Sopenharmony_ci 9671cb0ef41Sopenharmony_ci 9681cb0ef41Sopenharmony_ciSocket.prototype._writev = function(chunks, cb) { 9691cb0ef41Sopenharmony_ci this._writeGeneric(true, chunks, '', cb); 9701cb0ef41Sopenharmony_ci}; 9711cb0ef41Sopenharmony_ci 9721cb0ef41Sopenharmony_ci 9731cb0ef41Sopenharmony_ciSocket.prototype._write = function(data, encoding, cb) { 9741cb0ef41Sopenharmony_ci this._writeGeneric(false, data, encoding, cb); 9751cb0ef41Sopenharmony_ci}; 9761cb0ef41Sopenharmony_ci 9771cb0ef41Sopenharmony_ci 9781cb0ef41Sopenharmony_ci// Legacy alias. Having this is probably being overly cautious, but it doesn't 9791cb0ef41Sopenharmony_ci// really hurt anyone either. This can probably be removed safely if desired. 9801cb0ef41Sopenharmony_ciprotoGetter('_bytesDispatched', function _bytesDispatched() { 9811cb0ef41Sopenharmony_ci return this._handle ? this._handle.bytesWritten : this[kBytesWritten]; 9821cb0ef41Sopenharmony_ci}); 9831cb0ef41Sopenharmony_ci 9841cb0ef41Sopenharmony_ciprotoGetter('bytesWritten', function bytesWritten() { 9851cb0ef41Sopenharmony_ci let bytes = this._bytesDispatched; 9861cb0ef41Sopenharmony_ci const data = this._pendingData; 9871cb0ef41Sopenharmony_ci const encoding = this._pendingEncoding; 9881cb0ef41Sopenharmony_ci const writableBuffer = this.writableBuffer; 9891cb0ef41Sopenharmony_ci 9901cb0ef41Sopenharmony_ci if (!writableBuffer) 9911cb0ef41Sopenharmony_ci return undefined; 9921cb0ef41Sopenharmony_ci 9931cb0ef41Sopenharmony_ci for (const el of writableBuffer) { 9941cb0ef41Sopenharmony_ci bytes += el.chunk instanceof Buffer ? 9951cb0ef41Sopenharmony_ci el.chunk.length : 9961cb0ef41Sopenharmony_ci Buffer.byteLength(el.chunk, el.encoding); 9971cb0ef41Sopenharmony_ci } 9981cb0ef41Sopenharmony_ci 9991cb0ef41Sopenharmony_ci if (ArrayIsArray(data)) { 10001cb0ef41Sopenharmony_ci // Was a writev, iterate over chunks to get total length 10011cb0ef41Sopenharmony_ci for (let i = 0; i < data.length; i++) { 10021cb0ef41Sopenharmony_ci const chunk = data[i]; 10031cb0ef41Sopenharmony_ci 10041cb0ef41Sopenharmony_ci if (data.allBuffers || chunk instanceof Buffer) 10051cb0ef41Sopenharmony_ci bytes += chunk.length; 10061cb0ef41Sopenharmony_ci else 10071cb0ef41Sopenharmony_ci bytes += Buffer.byteLength(chunk.chunk, chunk.encoding); 10081cb0ef41Sopenharmony_ci } 10091cb0ef41Sopenharmony_ci } else if (data) { 10101cb0ef41Sopenharmony_ci // Writes are either a string or a Buffer. 10111cb0ef41Sopenharmony_ci if (typeof data !== 'string') 10121cb0ef41Sopenharmony_ci bytes += data.length; 10131cb0ef41Sopenharmony_ci else 10141cb0ef41Sopenharmony_ci bytes += Buffer.byteLength(data, encoding); 10151cb0ef41Sopenharmony_ci } 10161cb0ef41Sopenharmony_ci 10171cb0ef41Sopenharmony_ci return bytes; 10181cb0ef41Sopenharmony_ci}); 10191cb0ef41Sopenharmony_ci 10201cb0ef41Sopenharmony_ci 10211cb0ef41Sopenharmony_cifunction checkBindError(err, port, handle) { 10221cb0ef41Sopenharmony_ci // EADDRINUSE may not be reported until we call listen() or connect(). 10231cb0ef41Sopenharmony_ci // To complicate matters, a failed bind() followed by listen() or connect() 10241cb0ef41Sopenharmony_ci // will implicitly bind to a random port. Ergo, check that the socket is 10251cb0ef41Sopenharmony_ci // bound to the expected port before calling listen() or connect(). 10261cb0ef41Sopenharmony_ci // 10271cb0ef41Sopenharmony_ci // FIXME(bnoordhuis) Doesn't work for pipe handles, they don't have a 10281cb0ef41Sopenharmony_ci // getsockname() method. Non-issue for now, the cluster module doesn't 10291cb0ef41Sopenharmony_ci // really support pipes anyway. 10301cb0ef41Sopenharmony_ci if (err === 0 && port > 0 && handle.getsockname) { 10311cb0ef41Sopenharmony_ci const out = {}; 10321cb0ef41Sopenharmony_ci err = handle.getsockname(out); 10331cb0ef41Sopenharmony_ci if (err === 0 && port !== out.port) { 10341cb0ef41Sopenharmony_ci debug(`checkBindError, bound to ${out.port} instead of ${port}`); 10351cb0ef41Sopenharmony_ci err = UV_EADDRINUSE; 10361cb0ef41Sopenharmony_ci } 10371cb0ef41Sopenharmony_ci } 10381cb0ef41Sopenharmony_ci return err; 10391cb0ef41Sopenharmony_ci} 10401cb0ef41Sopenharmony_ci 10411cb0ef41Sopenharmony_ci 10421cb0ef41Sopenharmony_cifunction internalConnect( 10431cb0ef41Sopenharmony_ci self, address, port, addressType, localAddress, localPort, flags) { 10441cb0ef41Sopenharmony_ci // TODO return promise from Socket.prototype.connect which 10451cb0ef41Sopenharmony_ci // wraps _connectReq. 10461cb0ef41Sopenharmony_ci 10471cb0ef41Sopenharmony_ci assert(self.connecting); 10481cb0ef41Sopenharmony_ci 10491cb0ef41Sopenharmony_ci let err; 10501cb0ef41Sopenharmony_ci 10511cb0ef41Sopenharmony_ci if (localAddress || localPort) { 10521cb0ef41Sopenharmony_ci if (addressType === 4) { 10531cb0ef41Sopenharmony_ci localAddress = localAddress || DEFAULT_IPV4_ADDR; 10541cb0ef41Sopenharmony_ci err = self._handle.bind(localAddress, localPort); 10551cb0ef41Sopenharmony_ci } else { // addressType === 6 10561cb0ef41Sopenharmony_ci localAddress = localAddress || DEFAULT_IPV6_ADDR; 10571cb0ef41Sopenharmony_ci err = self._handle.bind6(localAddress, localPort, flags); 10581cb0ef41Sopenharmony_ci } 10591cb0ef41Sopenharmony_ci debug('connect: binding to localAddress: %s and localPort: %d (addressType: %d)', 10601cb0ef41Sopenharmony_ci localAddress, localPort, addressType); 10611cb0ef41Sopenharmony_ci 10621cb0ef41Sopenharmony_ci err = checkBindError(err, localPort, self._handle); 10631cb0ef41Sopenharmony_ci if (err) { 10641cb0ef41Sopenharmony_ci const ex = exceptionWithHostPort(err, 'bind', localAddress, localPort); 10651cb0ef41Sopenharmony_ci self.destroy(ex); 10661cb0ef41Sopenharmony_ci return; 10671cb0ef41Sopenharmony_ci } 10681cb0ef41Sopenharmony_ci } 10691cb0ef41Sopenharmony_ci 10701cb0ef41Sopenharmony_ci debug('connect: attempting to connect to %s:%d (addressType: %d)', address, port, addressType); 10711cb0ef41Sopenharmony_ci 10721cb0ef41Sopenharmony_ci if (addressType === 6 || addressType === 4) { 10731cb0ef41Sopenharmony_ci const req = new TCPConnectWrap(); 10741cb0ef41Sopenharmony_ci req.oncomplete = afterConnect; 10751cb0ef41Sopenharmony_ci req.address = address; 10761cb0ef41Sopenharmony_ci req.port = port; 10771cb0ef41Sopenharmony_ci req.localAddress = localAddress; 10781cb0ef41Sopenharmony_ci req.localPort = localPort; 10791cb0ef41Sopenharmony_ci 10801cb0ef41Sopenharmony_ci if (addressType === 4) 10811cb0ef41Sopenharmony_ci err = self._handle.connect(req, address, port); 10821cb0ef41Sopenharmony_ci else 10831cb0ef41Sopenharmony_ci err = self._handle.connect6(req, address, port); 10841cb0ef41Sopenharmony_ci } else { 10851cb0ef41Sopenharmony_ci const req = new PipeConnectWrap(); 10861cb0ef41Sopenharmony_ci req.address = address; 10871cb0ef41Sopenharmony_ci req.oncomplete = afterConnect; 10881cb0ef41Sopenharmony_ci 10891cb0ef41Sopenharmony_ci err = self._handle.connect(req, address); 10901cb0ef41Sopenharmony_ci } 10911cb0ef41Sopenharmony_ci 10921cb0ef41Sopenharmony_ci if (err) { 10931cb0ef41Sopenharmony_ci const sockname = self._getsockname(); 10941cb0ef41Sopenharmony_ci let details; 10951cb0ef41Sopenharmony_ci 10961cb0ef41Sopenharmony_ci if (sockname) { 10971cb0ef41Sopenharmony_ci details = sockname.address + ':' + sockname.port; 10981cb0ef41Sopenharmony_ci } 10991cb0ef41Sopenharmony_ci 11001cb0ef41Sopenharmony_ci const ex = exceptionWithHostPort(err, 'connect', address, port, details); 11011cb0ef41Sopenharmony_ci self.destroy(ex); 11021cb0ef41Sopenharmony_ci } else if ((addressType === 6 || addressType === 4) && hasObserver('net')) { 11031cb0ef41Sopenharmony_ci startPerf(self, kPerfHooksNetConnectContext, { type: 'net', name: 'connect', detail: { host: address, port } }); 11041cb0ef41Sopenharmony_ci } 11051cb0ef41Sopenharmony_ci} 11061cb0ef41Sopenharmony_ci 11071cb0ef41Sopenharmony_ci 11081cb0ef41Sopenharmony_cifunction internalConnectMultiple(context, canceled) { 11091cb0ef41Sopenharmony_ci clearTimeout(context[kTimeout]); 11101cb0ef41Sopenharmony_ci const self = context.socket; 11111cb0ef41Sopenharmony_ci 11121cb0ef41Sopenharmony_ci // All connections have been tried without success, destroy with error 11131cb0ef41Sopenharmony_ci if (canceled || context.current === context.addresses.length) { 11141cb0ef41Sopenharmony_ci self.destroy(aggregateErrors(context.errors)); 11151cb0ef41Sopenharmony_ci return; 11161cb0ef41Sopenharmony_ci } 11171cb0ef41Sopenharmony_ci 11181cb0ef41Sopenharmony_ci assert(self.connecting); 11191cb0ef41Sopenharmony_ci 11201cb0ef41Sopenharmony_ci const current = context.current++; 11211cb0ef41Sopenharmony_ci const handle = current === 0 ? self._handle : new TCP(TCPConstants.SOCKET); 11221cb0ef41Sopenharmony_ci const { localPort, port, flags } = context; 11231cb0ef41Sopenharmony_ci const { address, family: addressType } = context.addresses[current]; 11241cb0ef41Sopenharmony_ci let localAddress; 11251cb0ef41Sopenharmony_ci let err; 11261cb0ef41Sopenharmony_ci 11271cb0ef41Sopenharmony_ci if (localPort) { 11281cb0ef41Sopenharmony_ci if (addressType === 4) { 11291cb0ef41Sopenharmony_ci localAddress = DEFAULT_IPV4_ADDR; 11301cb0ef41Sopenharmony_ci err = handle.bind(localAddress, localPort); 11311cb0ef41Sopenharmony_ci } else { // addressType === 6 11321cb0ef41Sopenharmony_ci localAddress = DEFAULT_IPV6_ADDR; 11331cb0ef41Sopenharmony_ci err = handle.bind6(localAddress, localPort, flags); 11341cb0ef41Sopenharmony_ci } 11351cb0ef41Sopenharmony_ci 11361cb0ef41Sopenharmony_ci debug('connect/multiple: binding to localAddress: %s and localPort: %d (addressType: %d)', 11371cb0ef41Sopenharmony_ci localAddress, localPort, addressType); 11381cb0ef41Sopenharmony_ci 11391cb0ef41Sopenharmony_ci err = checkBindError(err, localPort, handle); 11401cb0ef41Sopenharmony_ci if (err) { 11411cb0ef41Sopenharmony_ci ArrayPrototypePush(context.errors, exceptionWithHostPort(err, 'bind', localAddress, localPort)); 11421cb0ef41Sopenharmony_ci internalConnectMultiple(context); 11431cb0ef41Sopenharmony_ci return; 11441cb0ef41Sopenharmony_ci } 11451cb0ef41Sopenharmony_ci } 11461cb0ef41Sopenharmony_ci 11471cb0ef41Sopenharmony_ci debug('connect/multiple: attempting to connect to %s:%d (addressType: %d)', address, port, addressType); 11481cb0ef41Sopenharmony_ci 11491cb0ef41Sopenharmony_ci const req = new TCPConnectWrap(); 11501cb0ef41Sopenharmony_ci req.oncomplete = FunctionPrototypeBind(afterConnectMultiple, undefined, context, current); 11511cb0ef41Sopenharmony_ci req.address = address; 11521cb0ef41Sopenharmony_ci req.port = port; 11531cb0ef41Sopenharmony_ci req.localAddress = localAddress; 11541cb0ef41Sopenharmony_ci req.localPort = localPort; 11551cb0ef41Sopenharmony_ci 11561cb0ef41Sopenharmony_ci ArrayPrototypePush(self.autoSelectFamilyAttemptedAddresses, `${address}:${port}`); 11571cb0ef41Sopenharmony_ci 11581cb0ef41Sopenharmony_ci if (addressType === 4) { 11591cb0ef41Sopenharmony_ci err = handle.connect(req, address, port); 11601cb0ef41Sopenharmony_ci } else { 11611cb0ef41Sopenharmony_ci err = handle.connect6(req, address, port); 11621cb0ef41Sopenharmony_ci } 11631cb0ef41Sopenharmony_ci 11641cb0ef41Sopenharmony_ci if (err) { 11651cb0ef41Sopenharmony_ci const sockname = self._getsockname(); 11661cb0ef41Sopenharmony_ci let details; 11671cb0ef41Sopenharmony_ci 11681cb0ef41Sopenharmony_ci if (sockname) { 11691cb0ef41Sopenharmony_ci details = sockname.address + ':' + sockname.port; 11701cb0ef41Sopenharmony_ci } 11711cb0ef41Sopenharmony_ci 11721cb0ef41Sopenharmony_ci ArrayPrototypePush(context.errors, exceptionWithHostPort(err, 'connect', address, port, details)); 11731cb0ef41Sopenharmony_ci internalConnectMultiple(context); 11741cb0ef41Sopenharmony_ci return; 11751cb0ef41Sopenharmony_ci } 11761cb0ef41Sopenharmony_ci 11771cb0ef41Sopenharmony_ci if (current < context.addresses.length - 1) { 11781cb0ef41Sopenharmony_ci debug('connect/multiple: setting the attempt timeout to %d ms', context.timeout); 11791cb0ef41Sopenharmony_ci 11801cb0ef41Sopenharmony_ci // If the attempt has not returned an error, start the connection timer 11811cb0ef41Sopenharmony_ci context[kTimeout] = setTimeout(internalConnectMultipleTimeout, context.timeout, context, req, handle); 11821cb0ef41Sopenharmony_ci } 11831cb0ef41Sopenharmony_ci} 11841cb0ef41Sopenharmony_ci 11851cb0ef41Sopenharmony_ciSocket.prototype.connect = function(...args) { 11861cb0ef41Sopenharmony_ci let normalized; 11871cb0ef41Sopenharmony_ci // If passed an array, it's treated as an array of arguments that have 11881cb0ef41Sopenharmony_ci // already been normalized (so we don't normalize more than once). This has 11891cb0ef41Sopenharmony_ci // been solved before in https://github.com/nodejs/node/pull/12342, but was 11901cb0ef41Sopenharmony_ci // reverted as it had unintended side effects. 11911cb0ef41Sopenharmony_ci if (ArrayIsArray(args[0]) && args[0][normalizedArgsSymbol]) { 11921cb0ef41Sopenharmony_ci normalized = args[0]; 11931cb0ef41Sopenharmony_ci } else { 11941cb0ef41Sopenharmony_ci normalized = normalizeArgs(args); 11951cb0ef41Sopenharmony_ci } 11961cb0ef41Sopenharmony_ci const options = normalized[0]; 11971cb0ef41Sopenharmony_ci const cb = normalized[1]; 11981cb0ef41Sopenharmony_ci 11991cb0ef41Sopenharmony_ci // options.port === null will be checked later. 12001cb0ef41Sopenharmony_ci if (options.port === undefined && options.path == null) 12011cb0ef41Sopenharmony_ci throw new ERR_MISSING_ARGS(['options', 'port', 'path']); 12021cb0ef41Sopenharmony_ci 12031cb0ef41Sopenharmony_ci if (this.write !== Socket.prototype.write) 12041cb0ef41Sopenharmony_ci this.write = Socket.prototype.write; 12051cb0ef41Sopenharmony_ci 12061cb0ef41Sopenharmony_ci if (this.destroyed) { 12071cb0ef41Sopenharmony_ci this._handle = null; 12081cb0ef41Sopenharmony_ci this._peername = null; 12091cb0ef41Sopenharmony_ci this._sockname = null; 12101cb0ef41Sopenharmony_ci } 12111cb0ef41Sopenharmony_ci 12121cb0ef41Sopenharmony_ci const { path } = options; 12131cb0ef41Sopenharmony_ci const pipe = !!path; 12141cb0ef41Sopenharmony_ci debug('pipe', pipe, path); 12151cb0ef41Sopenharmony_ci 12161cb0ef41Sopenharmony_ci if (!this._handle) { 12171cb0ef41Sopenharmony_ci this._handle = pipe ? 12181cb0ef41Sopenharmony_ci new Pipe(PipeConstants.SOCKET) : 12191cb0ef41Sopenharmony_ci new TCP(TCPConstants.SOCKET); 12201cb0ef41Sopenharmony_ci initSocketHandle(this); 12211cb0ef41Sopenharmony_ci } 12221cb0ef41Sopenharmony_ci 12231cb0ef41Sopenharmony_ci if (cb !== null) { 12241cb0ef41Sopenharmony_ci this.once('connect', cb); 12251cb0ef41Sopenharmony_ci } 12261cb0ef41Sopenharmony_ci 12271cb0ef41Sopenharmony_ci this._unrefTimer(); 12281cb0ef41Sopenharmony_ci 12291cb0ef41Sopenharmony_ci this.connecting = true; 12301cb0ef41Sopenharmony_ci 12311cb0ef41Sopenharmony_ci if (pipe) { 12321cb0ef41Sopenharmony_ci validateString(path, 'options.path'); 12331cb0ef41Sopenharmony_ci defaultTriggerAsyncIdScope( 12341cb0ef41Sopenharmony_ci this[async_id_symbol], internalConnect, this, path, 12351cb0ef41Sopenharmony_ci ); 12361cb0ef41Sopenharmony_ci } else { 12371cb0ef41Sopenharmony_ci lookupAndConnect(this, options); 12381cb0ef41Sopenharmony_ci } 12391cb0ef41Sopenharmony_ci return this; 12401cb0ef41Sopenharmony_ci}; 12411cb0ef41Sopenharmony_ci 12421cb0ef41Sopenharmony_ciSocket.prototype[kReinitializeHandle] = function reinitializeHandle(handle) { 12431cb0ef41Sopenharmony_ci this._handle?.close(); 12441cb0ef41Sopenharmony_ci 12451cb0ef41Sopenharmony_ci this._handle = handle; 12461cb0ef41Sopenharmony_ci this._handle[owner_symbol] = this; 12471cb0ef41Sopenharmony_ci 12481cb0ef41Sopenharmony_ci initSocketHandle(this); 12491cb0ef41Sopenharmony_ci}; 12501cb0ef41Sopenharmony_ci 12511cb0ef41Sopenharmony_cifunction socketToDnsFamily(family) { 12521cb0ef41Sopenharmony_ci switch (family) { 12531cb0ef41Sopenharmony_ci case 'IPv4': 12541cb0ef41Sopenharmony_ci return 4; 12551cb0ef41Sopenharmony_ci case 'IPv6': 12561cb0ef41Sopenharmony_ci return 6; 12571cb0ef41Sopenharmony_ci } 12581cb0ef41Sopenharmony_ci 12591cb0ef41Sopenharmony_ci return family; 12601cb0ef41Sopenharmony_ci} 12611cb0ef41Sopenharmony_ci 12621cb0ef41Sopenharmony_cifunction lookupAndConnect(self, options) { 12631cb0ef41Sopenharmony_ci const { localAddress, localPort } = options; 12641cb0ef41Sopenharmony_ci const host = options.host || 'localhost'; 12651cb0ef41Sopenharmony_ci let { port, autoSelectFamilyAttemptTimeout, autoSelectFamily } = options; 12661cb0ef41Sopenharmony_ci 12671cb0ef41Sopenharmony_ci if (localAddress && !isIP(localAddress)) { 12681cb0ef41Sopenharmony_ci throw new ERR_INVALID_IP_ADDRESS(localAddress); 12691cb0ef41Sopenharmony_ci } 12701cb0ef41Sopenharmony_ci 12711cb0ef41Sopenharmony_ci if (localPort) { 12721cb0ef41Sopenharmony_ci validateNumber(localPort, 'options.localPort'); 12731cb0ef41Sopenharmony_ci } 12741cb0ef41Sopenharmony_ci 12751cb0ef41Sopenharmony_ci if (typeof port !== 'undefined') { 12761cb0ef41Sopenharmony_ci if (typeof port !== 'number' && typeof port !== 'string') { 12771cb0ef41Sopenharmony_ci throw new ERR_INVALID_ARG_TYPE('options.port', 12781cb0ef41Sopenharmony_ci ['number', 'string'], port); 12791cb0ef41Sopenharmony_ci } 12801cb0ef41Sopenharmony_ci validatePort(port); 12811cb0ef41Sopenharmony_ci } 12821cb0ef41Sopenharmony_ci port |= 0; 12831cb0ef41Sopenharmony_ci 12841cb0ef41Sopenharmony_ci 12851cb0ef41Sopenharmony_ci if (autoSelectFamily != null) { 12861cb0ef41Sopenharmony_ci validateBoolean(autoSelectFamily, 'options.autoSelectFamily'); 12871cb0ef41Sopenharmony_ci } else { 12881cb0ef41Sopenharmony_ci autoSelectFamily = autoSelectFamilyDefault; 12891cb0ef41Sopenharmony_ci } 12901cb0ef41Sopenharmony_ci 12911cb0ef41Sopenharmony_ci if (autoSelectFamilyAttemptTimeout != null) { 12921cb0ef41Sopenharmony_ci validateInt32(autoSelectFamilyAttemptTimeout, 'options.autoSelectFamilyAttemptTimeout', 1); 12931cb0ef41Sopenharmony_ci 12941cb0ef41Sopenharmony_ci if (autoSelectFamilyAttemptTimeout < 10) { 12951cb0ef41Sopenharmony_ci autoSelectFamilyAttemptTimeout = 10; 12961cb0ef41Sopenharmony_ci } 12971cb0ef41Sopenharmony_ci } else { 12981cb0ef41Sopenharmony_ci autoSelectFamilyAttemptTimeout = autoSelectFamilyAttemptTimeoutDefault; 12991cb0ef41Sopenharmony_ci } 13001cb0ef41Sopenharmony_ci 13011cb0ef41Sopenharmony_ci // If host is an IP, skip performing a lookup 13021cb0ef41Sopenharmony_ci const addressType = isIP(host); 13031cb0ef41Sopenharmony_ci if (addressType) { 13041cb0ef41Sopenharmony_ci defaultTriggerAsyncIdScope(self[async_id_symbol], process.nextTick, () => { 13051cb0ef41Sopenharmony_ci if (self.connecting) 13061cb0ef41Sopenharmony_ci defaultTriggerAsyncIdScope( 13071cb0ef41Sopenharmony_ci self[async_id_symbol], 13081cb0ef41Sopenharmony_ci internalConnect, 13091cb0ef41Sopenharmony_ci self, host, port, addressType, localAddress, localPort, 13101cb0ef41Sopenharmony_ci ); 13111cb0ef41Sopenharmony_ci }); 13121cb0ef41Sopenharmony_ci return; 13131cb0ef41Sopenharmony_ci } 13141cb0ef41Sopenharmony_ci 13151cb0ef41Sopenharmony_ci if (options.lookup != null) 13161cb0ef41Sopenharmony_ci validateFunction(options.lookup, 'options.lookup'); 13171cb0ef41Sopenharmony_ci 13181cb0ef41Sopenharmony_ci if (dns === undefined) dns = require('dns'); 13191cb0ef41Sopenharmony_ci const dnsopts = { 13201cb0ef41Sopenharmony_ci family: socketToDnsFamily(options.family), 13211cb0ef41Sopenharmony_ci hints: options.hints || 0, 13221cb0ef41Sopenharmony_ci }; 13231cb0ef41Sopenharmony_ci 13241cb0ef41Sopenharmony_ci if (!isWindows && 13251cb0ef41Sopenharmony_ci dnsopts.family !== 4 && 13261cb0ef41Sopenharmony_ci dnsopts.family !== 6 && 13271cb0ef41Sopenharmony_ci dnsopts.hints === 0) { 13281cb0ef41Sopenharmony_ci dnsopts.hints = dns.ADDRCONFIG; 13291cb0ef41Sopenharmony_ci } 13301cb0ef41Sopenharmony_ci 13311cb0ef41Sopenharmony_ci debug('connect: find host', host); 13321cb0ef41Sopenharmony_ci debug('connect: dns options', dnsopts); 13331cb0ef41Sopenharmony_ci self._host = host; 13341cb0ef41Sopenharmony_ci const lookup = options.lookup || dns.lookup; 13351cb0ef41Sopenharmony_ci 13361cb0ef41Sopenharmony_ci if (dnsopts.family !== 4 && dnsopts.family !== 6 && !localAddress && autoSelectFamily) { 13371cb0ef41Sopenharmony_ci debug('connect: autodetecting'); 13381cb0ef41Sopenharmony_ci 13391cb0ef41Sopenharmony_ci dnsopts.all = true; 13401cb0ef41Sopenharmony_ci defaultTriggerAsyncIdScope(self[async_id_symbol], function() { 13411cb0ef41Sopenharmony_ci lookupAndConnectMultiple( 13421cb0ef41Sopenharmony_ci self, 13431cb0ef41Sopenharmony_ci async_id_symbol, 13441cb0ef41Sopenharmony_ci lookup, 13451cb0ef41Sopenharmony_ci host, 13461cb0ef41Sopenharmony_ci options, 13471cb0ef41Sopenharmony_ci dnsopts, 13481cb0ef41Sopenharmony_ci port, 13491cb0ef41Sopenharmony_ci localPort, 13501cb0ef41Sopenharmony_ci autoSelectFamilyAttemptTimeout, 13511cb0ef41Sopenharmony_ci ); 13521cb0ef41Sopenharmony_ci }); 13531cb0ef41Sopenharmony_ci 13541cb0ef41Sopenharmony_ci return; 13551cb0ef41Sopenharmony_ci } 13561cb0ef41Sopenharmony_ci 13571cb0ef41Sopenharmony_ci defaultTriggerAsyncIdScope(self[async_id_symbol], function() { 13581cb0ef41Sopenharmony_ci lookup(host, dnsopts, function emitLookup(err, ip, addressType) { 13591cb0ef41Sopenharmony_ci self.emit('lookup', err, ip, addressType, host); 13601cb0ef41Sopenharmony_ci 13611cb0ef41Sopenharmony_ci // It's possible we were destroyed while looking this up. 13621cb0ef41Sopenharmony_ci // XXX it would be great if we could cancel the promise returned by 13631cb0ef41Sopenharmony_ci // the look up. 13641cb0ef41Sopenharmony_ci if (!self.connecting) return; 13651cb0ef41Sopenharmony_ci 13661cb0ef41Sopenharmony_ci if (err) { 13671cb0ef41Sopenharmony_ci // net.createConnection() creates a net.Socket object and immediately 13681cb0ef41Sopenharmony_ci // calls net.Socket.connect() on it (that's us). There are no event 13691cb0ef41Sopenharmony_ci // listeners registered yet so defer the error event to the next tick. 13701cb0ef41Sopenharmony_ci process.nextTick(connectErrorNT, self, err); 13711cb0ef41Sopenharmony_ci } else if (!isIP(ip)) { 13721cb0ef41Sopenharmony_ci err = new ERR_INVALID_IP_ADDRESS(ip); 13731cb0ef41Sopenharmony_ci process.nextTick(connectErrorNT, self, err); 13741cb0ef41Sopenharmony_ci } else if (addressType !== 4 && addressType !== 6) { 13751cb0ef41Sopenharmony_ci err = new ERR_INVALID_ADDRESS_FAMILY(addressType, 13761cb0ef41Sopenharmony_ci options.host, 13771cb0ef41Sopenharmony_ci options.port); 13781cb0ef41Sopenharmony_ci process.nextTick(connectErrorNT, self, err); 13791cb0ef41Sopenharmony_ci } else { 13801cb0ef41Sopenharmony_ci self._unrefTimer(); 13811cb0ef41Sopenharmony_ci defaultTriggerAsyncIdScope( 13821cb0ef41Sopenharmony_ci self[async_id_symbol], 13831cb0ef41Sopenharmony_ci internalConnect, 13841cb0ef41Sopenharmony_ci self, ip, port, addressType, localAddress, localPort, 13851cb0ef41Sopenharmony_ci ); 13861cb0ef41Sopenharmony_ci } 13871cb0ef41Sopenharmony_ci }); 13881cb0ef41Sopenharmony_ci }); 13891cb0ef41Sopenharmony_ci} 13901cb0ef41Sopenharmony_ci 13911cb0ef41Sopenharmony_cifunction lookupAndConnectMultiple(self, async_id_symbol, lookup, host, options, dnsopts, port, localPort, timeout) { 13921cb0ef41Sopenharmony_ci defaultTriggerAsyncIdScope(self[async_id_symbol], function emitLookup() { 13931cb0ef41Sopenharmony_ci lookup(host, dnsopts, function emitLookup(err, addresses) { 13941cb0ef41Sopenharmony_ci // It's possible we were destroyed while looking this up. 13951cb0ef41Sopenharmony_ci // XXX it would be great if we could cancel the promise returned by 13961cb0ef41Sopenharmony_ci // the look up. 13971cb0ef41Sopenharmony_ci if (!self.connecting) { 13981cb0ef41Sopenharmony_ci return; 13991cb0ef41Sopenharmony_ci } else if (err) { 14001cb0ef41Sopenharmony_ci self.emit('lookup', err, undefined, undefined, host); 14011cb0ef41Sopenharmony_ci 14021cb0ef41Sopenharmony_ci // net.createConnection() creates a net.Socket object and immediately 14031cb0ef41Sopenharmony_ci // calls net.Socket.connect() on it (that's us). There are no event 14041cb0ef41Sopenharmony_ci // listeners registered yet so defer the error event to the next tick. 14051cb0ef41Sopenharmony_ci process.nextTick(connectErrorNT, self, err); 14061cb0ef41Sopenharmony_ci return; 14071cb0ef41Sopenharmony_ci } 14081cb0ef41Sopenharmony_ci 14091cb0ef41Sopenharmony_ci // Filter addresses by only keeping the one which are either IPv4 or IPV6. 14101cb0ef41Sopenharmony_ci // The first valid address determines which group has preference on the 14111cb0ef41Sopenharmony_ci // alternate family sorting which happens later. 14121cb0ef41Sopenharmony_ci const validIps = [[], []]; 14131cb0ef41Sopenharmony_ci let destinations; 14141cb0ef41Sopenharmony_ci for (let i = 0, l = addresses.length; i < l; i++) { 14151cb0ef41Sopenharmony_ci const address = addresses[i]; 14161cb0ef41Sopenharmony_ci const { address: ip, family: addressType } = address; 14171cb0ef41Sopenharmony_ci self.emit('lookup', err, ip, addressType, host); 14181cb0ef41Sopenharmony_ci 14191cb0ef41Sopenharmony_ci if (isIP(ip) && (addressType === 4 || addressType === 6)) { 14201cb0ef41Sopenharmony_ci if (!destinations) { 14211cb0ef41Sopenharmony_ci destinations = addressType === 6 ? { 6: 0, 4: 1 } : { 4: 0, 6: 1 }; 14221cb0ef41Sopenharmony_ci } 14231cb0ef41Sopenharmony_ci 14241cb0ef41Sopenharmony_ci ArrayPrototypePush(validIps[destinations[addressType]], address); 14251cb0ef41Sopenharmony_ci } 14261cb0ef41Sopenharmony_ci } 14271cb0ef41Sopenharmony_ci 14281cb0ef41Sopenharmony_ci // When no AAAA or A records are available, fail on the first one 14291cb0ef41Sopenharmony_ci if (!validIps[0].length && !validIps[1].length) { 14301cb0ef41Sopenharmony_ci const { address: firstIp, family: firstAddressType } = addresses[0]; 14311cb0ef41Sopenharmony_ci 14321cb0ef41Sopenharmony_ci if (!isIP(firstIp)) { 14331cb0ef41Sopenharmony_ci err = new ERR_INVALID_IP_ADDRESS(firstIp); 14341cb0ef41Sopenharmony_ci process.nextTick(connectErrorNT, self, err); 14351cb0ef41Sopenharmony_ci } else if (firstAddressType !== 4 && firstAddressType !== 6) { 14361cb0ef41Sopenharmony_ci err = new ERR_INVALID_ADDRESS_FAMILY(firstAddressType, 14371cb0ef41Sopenharmony_ci options.host, 14381cb0ef41Sopenharmony_ci options.port); 14391cb0ef41Sopenharmony_ci process.nextTick(connectErrorNT, self, err); 14401cb0ef41Sopenharmony_ci } 14411cb0ef41Sopenharmony_ci 14421cb0ef41Sopenharmony_ci return; 14431cb0ef41Sopenharmony_ci } 14441cb0ef41Sopenharmony_ci 14451cb0ef41Sopenharmony_ci // Sort addresses alternating families 14461cb0ef41Sopenharmony_ci const toAttempt = []; 14471cb0ef41Sopenharmony_ci for (let i = 0, l = MathMax(validIps[0].length, validIps[1].length); i < l; i++) { 14481cb0ef41Sopenharmony_ci if (i in validIps[0]) { 14491cb0ef41Sopenharmony_ci ArrayPrototypePush(toAttempt, validIps[0][i]); 14501cb0ef41Sopenharmony_ci } 14511cb0ef41Sopenharmony_ci if (i in validIps[1]) { 14521cb0ef41Sopenharmony_ci ArrayPrototypePush(toAttempt, validIps[1][i]); 14531cb0ef41Sopenharmony_ci } 14541cb0ef41Sopenharmony_ci } 14551cb0ef41Sopenharmony_ci 14561cb0ef41Sopenharmony_ci self.autoSelectFamilyAttemptedAddresses = []; 14571cb0ef41Sopenharmony_ci 14581cb0ef41Sopenharmony_ci const context = { 14591cb0ef41Sopenharmony_ci socket: self, 14601cb0ef41Sopenharmony_ci addresses: toAttempt, 14611cb0ef41Sopenharmony_ci current: 0, 14621cb0ef41Sopenharmony_ci port, 14631cb0ef41Sopenharmony_ci localPort, 14641cb0ef41Sopenharmony_ci timeout, 14651cb0ef41Sopenharmony_ci [kTimeout]: null, 14661cb0ef41Sopenharmony_ci errors: [], 14671cb0ef41Sopenharmony_ci }; 14681cb0ef41Sopenharmony_ci 14691cb0ef41Sopenharmony_ci self._unrefTimer(); 14701cb0ef41Sopenharmony_ci defaultTriggerAsyncIdScope(self[async_id_symbol], internalConnectMultiple, context); 14711cb0ef41Sopenharmony_ci }); 14721cb0ef41Sopenharmony_ci }); 14731cb0ef41Sopenharmony_ci} 14741cb0ef41Sopenharmony_ci 14751cb0ef41Sopenharmony_cifunction connectErrorNT(self, err) { 14761cb0ef41Sopenharmony_ci self.destroy(err); 14771cb0ef41Sopenharmony_ci} 14781cb0ef41Sopenharmony_ci 14791cb0ef41Sopenharmony_ci 14801cb0ef41Sopenharmony_ciSocket.prototype.ref = function() { 14811cb0ef41Sopenharmony_ci if (!this._handle) { 14821cb0ef41Sopenharmony_ci this.once('connect', this.ref); 14831cb0ef41Sopenharmony_ci return this; 14841cb0ef41Sopenharmony_ci } 14851cb0ef41Sopenharmony_ci 14861cb0ef41Sopenharmony_ci if (typeof this._handle.ref === 'function') { 14871cb0ef41Sopenharmony_ci this._handle.ref(); 14881cb0ef41Sopenharmony_ci } 14891cb0ef41Sopenharmony_ci 14901cb0ef41Sopenharmony_ci return this; 14911cb0ef41Sopenharmony_ci}; 14921cb0ef41Sopenharmony_ci 14931cb0ef41Sopenharmony_ci 14941cb0ef41Sopenharmony_ciSocket.prototype.unref = function() { 14951cb0ef41Sopenharmony_ci if (!this._handle) { 14961cb0ef41Sopenharmony_ci this.once('connect', this.unref); 14971cb0ef41Sopenharmony_ci return this; 14981cb0ef41Sopenharmony_ci } 14991cb0ef41Sopenharmony_ci 15001cb0ef41Sopenharmony_ci if (typeof this._handle.unref === 'function') { 15011cb0ef41Sopenharmony_ci this._handle.unref(); 15021cb0ef41Sopenharmony_ci } 15031cb0ef41Sopenharmony_ci 15041cb0ef41Sopenharmony_ci return this; 15051cb0ef41Sopenharmony_ci}; 15061cb0ef41Sopenharmony_ci 15071cb0ef41Sopenharmony_ci 15081cb0ef41Sopenharmony_cifunction afterConnect(status, handle, req, readable, writable) { 15091cb0ef41Sopenharmony_ci const self = handle[owner_symbol]; 15101cb0ef41Sopenharmony_ci 15111cb0ef41Sopenharmony_ci // Callback may come after call to destroy 15121cb0ef41Sopenharmony_ci if (self.destroyed) { 15131cb0ef41Sopenharmony_ci return; 15141cb0ef41Sopenharmony_ci } 15151cb0ef41Sopenharmony_ci 15161cb0ef41Sopenharmony_ci debug('afterConnect'); 15171cb0ef41Sopenharmony_ci 15181cb0ef41Sopenharmony_ci assert(self.connecting); 15191cb0ef41Sopenharmony_ci self.connecting = false; 15201cb0ef41Sopenharmony_ci self._sockname = null; 15211cb0ef41Sopenharmony_ci 15221cb0ef41Sopenharmony_ci if (status === 0) { 15231cb0ef41Sopenharmony_ci if (self.readable && !readable) { 15241cb0ef41Sopenharmony_ci self.push(null); 15251cb0ef41Sopenharmony_ci self.read(); 15261cb0ef41Sopenharmony_ci } 15271cb0ef41Sopenharmony_ci if (self.writable && !writable) { 15281cb0ef41Sopenharmony_ci self.end(); 15291cb0ef41Sopenharmony_ci } 15301cb0ef41Sopenharmony_ci self._unrefTimer(); 15311cb0ef41Sopenharmony_ci 15321cb0ef41Sopenharmony_ci if (self[kSetNoDelay] && self._handle.setNoDelay) { 15331cb0ef41Sopenharmony_ci self._handle.setNoDelay(true); 15341cb0ef41Sopenharmony_ci } 15351cb0ef41Sopenharmony_ci 15361cb0ef41Sopenharmony_ci if (self[kSetKeepAlive] && self._handle.setKeepAlive) { 15371cb0ef41Sopenharmony_ci self._handle.setKeepAlive(true, self[kSetKeepAliveInitialDelay]); 15381cb0ef41Sopenharmony_ci } 15391cb0ef41Sopenharmony_ci 15401cb0ef41Sopenharmony_ci self.emit('connect'); 15411cb0ef41Sopenharmony_ci self.emit('ready'); 15421cb0ef41Sopenharmony_ci 15431cb0ef41Sopenharmony_ci // Start the first read, or get an immediate EOF. 15441cb0ef41Sopenharmony_ci // this doesn't actually consume any bytes, because len=0. 15451cb0ef41Sopenharmony_ci if (readable && !self.isPaused()) 15461cb0ef41Sopenharmony_ci self.read(0); 15471cb0ef41Sopenharmony_ci if (self[kPerfHooksNetConnectContext] && hasObserver('net')) { 15481cb0ef41Sopenharmony_ci stopPerf(self, kPerfHooksNetConnectContext); 15491cb0ef41Sopenharmony_ci } 15501cb0ef41Sopenharmony_ci } else { 15511cb0ef41Sopenharmony_ci let details; 15521cb0ef41Sopenharmony_ci if (req.localAddress && req.localPort) { 15531cb0ef41Sopenharmony_ci details = req.localAddress + ':' + req.localPort; 15541cb0ef41Sopenharmony_ci } 15551cb0ef41Sopenharmony_ci const ex = exceptionWithHostPort(status, 15561cb0ef41Sopenharmony_ci 'connect', 15571cb0ef41Sopenharmony_ci req.address, 15581cb0ef41Sopenharmony_ci req.port, 15591cb0ef41Sopenharmony_ci details); 15601cb0ef41Sopenharmony_ci if (details) { 15611cb0ef41Sopenharmony_ci ex.localAddress = req.localAddress; 15621cb0ef41Sopenharmony_ci ex.localPort = req.localPort; 15631cb0ef41Sopenharmony_ci } 15641cb0ef41Sopenharmony_ci self.destroy(ex); 15651cb0ef41Sopenharmony_ci } 15661cb0ef41Sopenharmony_ci} 15671cb0ef41Sopenharmony_ci 15681cb0ef41Sopenharmony_cifunction afterConnectMultiple(context, current, status, handle, req, readable, writable) { 15691cb0ef41Sopenharmony_ci // Make sure another connection is not spawned 15701cb0ef41Sopenharmony_ci clearTimeout(context[kTimeout]); 15711cb0ef41Sopenharmony_ci 15721cb0ef41Sopenharmony_ci // One of the connection has completed and correctly dispatched but after timeout, ignore this one 15731cb0ef41Sopenharmony_ci if (status === 0 && current !== context.current - 1) { 15741cb0ef41Sopenharmony_ci debug('connect/multiple: ignoring successful but timedout connection to %s:%s', req.address, req.port); 15751cb0ef41Sopenharmony_ci handle.close(); 15761cb0ef41Sopenharmony_ci return; 15771cb0ef41Sopenharmony_ci } 15781cb0ef41Sopenharmony_ci 15791cb0ef41Sopenharmony_ci const self = context.socket; 15801cb0ef41Sopenharmony_ci 15811cb0ef41Sopenharmony_ci 15821cb0ef41Sopenharmony_ci // Some error occurred, add to the list of exceptions 15831cb0ef41Sopenharmony_ci if (status !== 0) { 15841cb0ef41Sopenharmony_ci let details; 15851cb0ef41Sopenharmony_ci if (req.localAddress && req.localPort) { 15861cb0ef41Sopenharmony_ci details = req.localAddress + ':' + req.localPort; 15871cb0ef41Sopenharmony_ci } 15881cb0ef41Sopenharmony_ci const ex = exceptionWithHostPort(status, 15891cb0ef41Sopenharmony_ci 'connect', 15901cb0ef41Sopenharmony_ci req.address, 15911cb0ef41Sopenharmony_ci req.port, 15921cb0ef41Sopenharmony_ci details); 15931cb0ef41Sopenharmony_ci if (details) { 15941cb0ef41Sopenharmony_ci ex.localAddress = req.localAddress; 15951cb0ef41Sopenharmony_ci ex.localPort = req.localPort; 15961cb0ef41Sopenharmony_ci } 15971cb0ef41Sopenharmony_ci 15981cb0ef41Sopenharmony_ci ArrayPrototypePush(context.errors, ex); 15991cb0ef41Sopenharmony_ci 16001cb0ef41Sopenharmony_ci // Try the next address 16011cb0ef41Sopenharmony_ci internalConnectMultiple(context, status === UV_ECANCELED); 16021cb0ef41Sopenharmony_ci return; 16031cb0ef41Sopenharmony_ci } 16041cb0ef41Sopenharmony_ci 16051cb0ef41Sopenharmony_ci // One of the connection has completed and correctly dispatched but after timeout, ignore this one 16061cb0ef41Sopenharmony_ci if (status === 0 && current !== context.current - 1) { 16071cb0ef41Sopenharmony_ci debug('connect/multiple: ignoring successful but timedout connection to %s:%s', req.address, req.port); 16081cb0ef41Sopenharmony_ci handle.close(); 16091cb0ef41Sopenharmony_ci return; 16101cb0ef41Sopenharmony_ci } 16111cb0ef41Sopenharmony_ci 16121cb0ef41Sopenharmony_ci if (context.current > 1 && self[kReinitializeHandle]) { 16131cb0ef41Sopenharmony_ci self[kReinitializeHandle](handle); 16141cb0ef41Sopenharmony_ci handle = self._handle; 16151cb0ef41Sopenharmony_ci } 16161cb0ef41Sopenharmony_ci 16171cb0ef41Sopenharmony_ci if (hasObserver('net')) { 16181cb0ef41Sopenharmony_ci startPerf( 16191cb0ef41Sopenharmony_ci self, 16201cb0ef41Sopenharmony_ci kPerfHooksNetConnectContext, 16211cb0ef41Sopenharmony_ci { type: 'net', name: 'connect', detail: { host: req.address, port: req.port } }, 16221cb0ef41Sopenharmony_ci ); 16231cb0ef41Sopenharmony_ci } 16241cb0ef41Sopenharmony_ci 16251cb0ef41Sopenharmony_ci afterConnect(status, handle, req, readable, writable); 16261cb0ef41Sopenharmony_ci} 16271cb0ef41Sopenharmony_ci 16281cb0ef41Sopenharmony_cifunction internalConnectMultipleTimeout(context, req, handle) { 16291cb0ef41Sopenharmony_ci debug('connect/multiple: connection to %s:%s timed out', req.address, req.port); 16301cb0ef41Sopenharmony_ci req.oncomplete = undefined; 16311cb0ef41Sopenharmony_ci handle.close(); 16321cb0ef41Sopenharmony_ci internalConnectMultiple(context); 16331cb0ef41Sopenharmony_ci} 16341cb0ef41Sopenharmony_ci 16351cb0ef41Sopenharmony_cifunction addAbortSignalOption(self, options) { 16361cb0ef41Sopenharmony_ci if (options?.signal === undefined) { 16371cb0ef41Sopenharmony_ci return; 16381cb0ef41Sopenharmony_ci } 16391cb0ef41Sopenharmony_ci validateAbortSignal(options.signal, 'options.signal'); 16401cb0ef41Sopenharmony_ci const { signal } = options; 16411cb0ef41Sopenharmony_ci const onAborted = () => { 16421cb0ef41Sopenharmony_ci self.close(); 16431cb0ef41Sopenharmony_ci }; 16441cb0ef41Sopenharmony_ci if (signal.aborted) { 16451cb0ef41Sopenharmony_ci process.nextTick(onAborted); 16461cb0ef41Sopenharmony_ci } else { 16471cb0ef41Sopenharmony_ci signal.addEventListener('abort', onAborted); 16481cb0ef41Sopenharmony_ci self.once('close', () => signal.removeEventListener('abort', onAborted)); 16491cb0ef41Sopenharmony_ci } 16501cb0ef41Sopenharmony_ci} 16511cb0ef41Sopenharmony_ci 16521cb0ef41Sopenharmony_cifunction Server(options, connectionListener) { 16531cb0ef41Sopenharmony_ci if (!(this instanceof Server)) 16541cb0ef41Sopenharmony_ci return new Server(options, connectionListener); 16551cb0ef41Sopenharmony_ci 16561cb0ef41Sopenharmony_ci EventEmitter.call(this); 16571cb0ef41Sopenharmony_ci 16581cb0ef41Sopenharmony_ci if (typeof options === 'function') { 16591cb0ef41Sopenharmony_ci connectionListener = options; 16601cb0ef41Sopenharmony_ci options = kEmptyObject; 16611cb0ef41Sopenharmony_ci this.on('connection', connectionListener); 16621cb0ef41Sopenharmony_ci } else if (options == null || typeof options === 'object') { 16631cb0ef41Sopenharmony_ci options = { ...options }; 16641cb0ef41Sopenharmony_ci 16651cb0ef41Sopenharmony_ci if (typeof connectionListener === 'function') { 16661cb0ef41Sopenharmony_ci this.on('connection', connectionListener); 16671cb0ef41Sopenharmony_ci } 16681cb0ef41Sopenharmony_ci } else { 16691cb0ef41Sopenharmony_ci throw new ERR_INVALID_ARG_TYPE('options', 'Object', options); 16701cb0ef41Sopenharmony_ci } 16711cb0ef41Sopenharmony_ci if (typeof options.keepAliveInitialDelay !== 'undefined') { 16721cb0ef41Sopenharmony_ci validateNumber( 16731cb0ef41Sopenharmony_ci options.keepAliveInitialDelay, 'options.keepAliveInitialDelay', 16741cb0ef41Sopenharmony_ci ); 16751cb0ef41Sopenharmony_ci 16761cb0ef41Sopenharmony_ci if (options.keepAliveInitialDelay < 0) { 16771cb0ef41Sopenharmony_ci options.keepAliveInitialDelay = 0; 16781cb0ef41Sopenharmony_ci } 16791cb0ef41Sopenharmony_ci } 16801cb0ef41Sopenharmony_ci if (typeof options.highWaterMark !== 'undefined') { 16811cb0ef41Sopenharmony_ci validateNumber( 16821cb0ef41Sopenharmony_ci options.highWaterMark, 'options.highWaterMark', 16831cb0ef41Sopenharmony_ci ); 16841cb0ef41Sopenharmony_ci 16851cb0ef41Sopenharmony_ci if (options.highWaterMark < 0) { 16861cb0ef41Sopenharmony_ci options.highWaterMark = getDefaultHighWaterMark(); 16871cb0ef41Sopenharmony_ci } 16881cb0ef41Sopenharmony_ci } 16891cb0ef41Sopenharmony_ci 16901cb0ef41Sopenharmony_ci this._connections = 0; 16911cb0ef41Sopenharmony_ci 16921cb0ef41Sopenharmony_ci this[async_id_symbol] = -1; 16931cb0ef41Sopenharmony_ci this._handle = null; 16941cb0ef41Sopenharmony_ci this._usingWorkers = false; 16951cb0ef41Sopenharmony_ci this._workers = []; 16961cb0ef41Sopenharmony_ci this._unref = false; 16971cb0ef41Sopenharmony_ci 16981cb0ef41Sopenharmony_ci this.allowHalfOpen = options.allowHalfOpen || false; 16991cb0ef41Sopenharmony_ci this.pauseOnConnect = !!options.pauseOnConnect; 17001cb0ef41Sopenharmony_ci this.noDelay = Boolean(options.noDelay); 17011cb0ef41Sopenharmony_ci this.keepAlive = Boolean(options.keepAlive); 17021cb0ef41Sopenharmony_ci this.keepAliveInitialDelay = ~~(options.keepAliveInitialDelay / 1000); 17031cb0ef41Sopenharmony_ci this.highWaterMark = options.highWaterMark ?? getDefaultHighWaterMark(); 17041cb0ef41Sopenharmony_ci} 17051cb0ef41Sopenharmony_ciObjectSetPrototypeOf(Server.prototype, EventEmitter.prototype); 17061cb0ef41Sopenharmony_ciObjectSetPrototypeOf(Server, EventEmitter); 17071cb0ef41Sopenharmony_ci 17081cb0ef41Sopenharmony_ci 17091cb0ef41Sopenharmony_cifunction toNumber(x) { return (x = Number(x)) >= 0 ? x : false; } 17101cb0ef41Sopenharmony_ci 17111cb0ef41Sopenharmony_ci// Returns handle if it can be created, or error code if it can't 17121cb0ef41Sopenharmony_cifunction createServerHandle(address, port, addressType, fd, flags) { 17131cb0ef41Sopenharmony_ci let err = 0; 17141cb0ef41Sopenharmony_ci // Assign handle in listen, and clean up if bind or listen fails 17151cb0ef41Sopenharmony_ci let handle; 17161cb0ef41Sopenharmony_ci 17171cb0ef41Sopenharmony_ci let isTCP = false; 17181cb0ef41Sopenharmony_ci if (typeof fd === 'number' && fd >= 0) { 17191cb0ef41Sopenharmony_ci try { 17201cb0ef41Sopenharmony_ci handle = createHandle(fd, true); 17211cb0ef41Sopenharmony_ci } catch (e) { 17221cb0ef41Sopenharmony_ci // Not a fd we can listen on. This will trigger an error. 17231cb0ef41Sopenharmony_ci debug('listen invalid fd=%d:', fd, e.message); 17241cb0ef41Sopenharmony_ci return UV_EINVAL; 17251cb0ef41Sopenharmony_ci } 17261cb0ef41Sopenharmony_ci 17271cb0ef41Sopenharmony_ci err = handle.open(fd); 17281cb0ef41Sopenharmony_ci if (err) 17291cb0ef41Sopenharmony_ci return err; 17301cb0ef41Sopenharmony_ci 17311cb0ef41Sopenharmony_ci assert(!address && !port); 17321cb0ef41Sopenharmony_ci } else if (port === -1 && addressType === -1) { 17331cb0ef41Sopenharmony_ci handle = new Pipe(PipeConstants.SERVER); 17341cb0ef41Sopenharmony_ci if (isWindows) { 17351cb0ef41Sopenharmony_ci const instances = NumberParseInt(process.env.NODE_PENDING_PIPE_INSTANCES); 17361cb0ef41Sopenharmony_ci if (!NumberIsNaN(instances)) { 17371cb0ef41Sopenharmony_ci handle.setPendingInstances(instances); 17381cb0ef41Sopenharmony_ci } 17391cb0ef41Sopenharmony_ci } 17401cb0ef41Sopenharmony_ci } else { 17411cb0ef41Sopenharmony_ci handle = new TCP(TCPConstants.SERVER); 17421cb0ef41Sopenharmony_ci isTCP = true; 17431cb0ef41Sopenharmony_ci } 17441cb0ef41Sopenharmony_ci 17451cb0ef41Sopenharmony_ci if (address || port || isTCP) { 17461cb0ef41Sopenharmony_ci debug('bind to', address || 'any'); 17471cb0ef41Sopenharmony_ci if (!address) { 17481cb0ef41Sopenharmony_ci // Try binding to ipv6 first 17491cb0ef41Sopenharmony_ci err = handle.bind6(DEFAULT_IPV6_ADDR, port, flags); 17501cb0ef41Sopenharmony_ci if (err) { 17511cb0ef41Sopenharmony_ci handle.close(); 17521cb0ef41Sopenharmony_ci // Fallback to ipv4 17531cb0ef41Sopenharmony_ci return createServerHandle(DEFAULT_IPV4_ADDR, port); 17541cb0ef41Sopenharmony_ci } 17551cb0ef41Sopenharmony_ci } else if (addressType === 6) { 17561cb0ef41Sopenharmony_ci err = handle.bind6(address, port, flags); 17571cb0ef41Sopenharmony_ci } else { 17581cb0ef41Sopenharmony_ci err = handle.bind(address, port); 17591cb0ef41Sopenharmony_ci } 17601cb0ef41Sopenharmony_ci } 17611cb0ef41Sopenharmony_ci 17621cb0ef41Sopenharmony_ci if (err) { 17631cb0ef41Sopenharmony_ci handle.close(); 17641cb0ef41Sopenharmony_ci return err; 17651cb0ef41Sopenharmony_ci } 17661cb0ef41Sopenharmony_ci 17671cb0ef41Sopenharmony_ci return handle; 17681cb0ef41Sopenharmony_ci} 17691cb0ef41Sopenharmony_ci 17701cb0ef41Sopenharmony_cifunction setupListenHandle(address, port, addressType, backlog, fd, flags) { 17711cb0ef41Sopenharmony_ci debug('setupListenHandle', address, port, addressType, backlog, fd); 17721cb0ef41Sopenharmony_ci 17731cb0ef41Sopenharmony_ci // If there is not yet a handle, we need to create one and bind. 17741cb0ef41Sopenharmony_ci // In the case of a server sent via IPC, we don't need to do this. 17751cb0ef41Sopenharmony_ci if (this._handle) { 17761cb0ef41Sopenharmony_ci debug('setupListenHandle: have a handle already'); 17771cb0ef41Sopenharmony_ci } else { 17781cb0ef41Sopenharmony_ci debug('setupListenHandle: create a handle'); 17791cb0ef41Sopenharmony_ci 17801cb0ef41Sopenharmony_ci let rval = null; 17811cb0ef41Sopenharmony_ci 17821cb0ef41Sopenharmony_ci // Try to bind to the unspecified IPv6 address, see if IPv6 is available 17831cb0ef41Sopenharmony_ci if (!address && typeof fd !== 'number') { 17841cb0ef41Sopenharmony_ci rval = createServerHandle(DEFAULT_IPV6_ADDR, port, 6, fd, flags); 17851cb0ef41Sopenharmony_ci 17861cb0ef41Sopenharmony_ci if (typeof rval === 'number') { 17871cb0ef41Sopenharmony_ci rval = null; 17881cb0ef41Sopenharmony_ci address = DEFAULT_IPV4_ADDR; 17891cb0ef41Sopenharmony_ci addressType = 4; 17901cb0ef41Sopenharmony_ci } else { 17911cb0ef41Sopenharmony_ci address = DEFAULT_IPV6_ADDR; 17921cb0ef41Sopenharmony_ci addressType = 6; 17931cb0ef41Sopenharmony_ci } 17941cb0ef41Sopenharmony_ci } 17951cb0ef41Sopenharmony_ci 17961cb0ef41Sopenharmony_ci if (rval === null) 17971cb0ef41Sopenharmony_ci rval = createServerHandle(address, port, addressType, fd, flags); 17981cb0ef41Sopenharmony_ci 17991cb0ef41Sopenharmony_ci if (typeof rval === 'number') { 18001cb0ef41Sopenharmony_ci const error = uvExceptionWithHostPort(rval, 'listen', address, port); 18011cb0ef41Sopenharmony_ci process.nextTick(emitErrorNT, this, error); 18021cb0ef41Sopenharmony_ci return; 18031cb0ef41Sopenharmony_ci } 18041cb0ef41Sopenharmony_ci this._handle = rval; 18051cb0ef41Sopenharmony_ci } 18061cb0ef41Sopenharmony_ci 18071cb0ef41Sopenharmony_ci this[async_id_symbol] = getNewAsyncId(this._handle); 18081cb0ef41Sopenharmony_ci this._handle.onconnection = onconnection; 18091cb0ef41Sopenharmony_ci this._handle[owner_symbol] = this; 18101cb0ef41Sopenharmony_ci 18111cb0ef41Sopenharmony_ci // Use a backlog of 512 entries. We pass 511 to the listen() call because 18121cb0ef41Sopenharmony_ci // the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1); 18131cb0ef41Sopenharmony_ci // which will thus give us a backlog of 512 entries. 18141cb0ef41Sopenharmony_ci const err = this._handle.listen(backlog || 511); 18151cb0ef41Sopenharmony_ci 18161cb0ef41Sopenharmony_ci if (err) { 18171cb0ef41Sopenharmony_ci const ex = uvExceptionWithHostPort(err, 'listen', address, port); 18181cb0ef41Sopenharmony_ci this._handle.close(); 18191cb0ef41Sopenharmony_ci this._handle = null; 18201cb0ef41Sopenharmony_ci defaultTriggerAsyncIdScope(this[async_id_symbol], 18211cb0ef41Sopenharmony_ci process.nextTick, 18221cb0ef41Sopenharmony_ci emitErrorNT, 18231cb0ef41Sopenharmony_ci this, 18241cb0ef41Sopenharmony_ci ex); 18251cb0ef41Sopenharmony_ci return; 18261cb0ef41Sopenharmony_ci } 18271cb0ef41Sopenharmony_ci 18281cb0ef41Sopenharmony_ci // Generate connection key, this should be unique to the connection 18291cb0ef41Sopenharmony_ci this._connectionKey = addressType + ':' + address + ':' + port; 18301cb0ef41Sopenharmony_ci 18311cb0ef41Sopenharmony_ci // Unref the handle if the server was unref'ed prior to listening 18321cb0ef41Sopenharmony_ci if (this._unref) 18331cb0ef41Sopenharmony_ci this.unref(); 18341cb0ef41Sopenharmony_ci 18351cb0ef41Sopenharmony_ci defaultTriggerAsyncIdScope(this[async_id_symbol], 18361cb0ef41Sopenharmony_ci process.nextTick, 18371cb0ef41Sopenharmony_ci emitListeningNT, 18381cb0ef41Sopenharmony_ci this); 18391cb0ef41Sopenharmony_ci} 18401cb0ef41Sopenharmony_ci 18411cb0ef41Sopenharmony_ciServer.prototype._listen2 = setupListenHandle; // legacy alias 18421cb0ef41Sopenharmony_ci 18431cb0ef41Sopenharmony_cifunction emitErrorNT(self, err) { 18441cb0ef41Sopenharmony_ci self.emit('error', err); 18451cb0ef41Sopenharmony_ci} 18461cb0ef41Sopenharmony_ci 18471cb0ef41Sopenharmony_ci 18481cb0ef41Sopenharmony_cifunction emitListeningNT(self) { 18491cb0ef41Sopenharmony_ci // Ensure handle hasn't closed 18501cb0ef41Sopenharmony_ci if (self._handle) 18511cb0ef41Sopenharmony_ci self.emit('listening'); 18521cb0ef41Sopenharmony_ci} 18531cb0ef41Sopenharmony_ci 18541cb0ef41Sopenharmony_ci 18551cb0ef41Sopenharmony_cifunction listenInCluster(server, address, port, addressType, 18561cb0ef41Sopenharmony_ci backlog, fd, exclusive, flags, options) { 18571cb0ef41Sopenharmony_ci exclusive = !!exclusive; 18581cb0ef41Sopenharmony_ci 18591cb0ef41Sopenharmony_ci if (cluster === undefined) cluster = require('cluster'); 18601cb0ef41Sopenharmony_ci 18611cb0ef41Sopenharmony_ci if (cluster.isPrimary || exclusive) { 18621cb0ef41Sopenharmony_ci // Will create a new handle 18631cb0ef41Sopenharmony_ci // _listen2 sets up the listened handle, it is still named like this 18641cb0ef41Sopenharmony_ci // to avoid breaking code that wraps this method 18651cb0ef41Sopenharmony_ci server._listen2(address, port, addressType, backlog, fd, flags); 18661cb0ef41Sopenharmony_ci return; 18671cb0ef41Sopenharmony_ci } 18681cb0ef41Sopenharmony_ci 18691cb0ef41Sopenharmony_ci const serverQuery = { 18701cb0ef41Sopenharmony_ci address: address, 18711cb0ef41Sopenharmony_ci port: port, 18721cb0ef41Sopenharmony_ci addressType: addressType, 18731cb0ef41Sopenharmony_ci fd: fd, 18741cb0ef41Sopenharmony_ci flags, 18751cb0ef41Sopenharmony_ci backlog, 18761cb0ef41Sopenharmony_ci ...options, 18771cb0ef41Sopenharmony_ci }; 18781cb0ef41Sopenharmony_ci // Get the primary's server handle, and listen on it 18791cb0ef41Sopenharmony_ci cluster._getServer(server, serverQuery, listenOnPrimaryHandle); 18801cb0ef41Sopenharmony_ci 18811cb0ef41Sopenharmony_ci function listenOnPrimaryHandle(err, handle) { 18821cb0ef41Sopenharmony_ci err = checkBindError(err, port, handle); 18831cb0ef41Sopenharmony_ci 18841cb0ef41Sopenharmony_ci if (err) { 18851cb0ef41Sopenharmony_ci const ex = exceptionWithHostPort(err, 'bind', address, port); 18861cb0ef41Sopenharmony_ci return server.emit('error', ex); 18871cb0ef41Sopenharmony_ci } 18881cb0ef41Sopenharmony_ci 18891cb0ef41Sopenharmony_ci // Reuse primary's server handle 18901cb0ef41Sopenharmony_ci server._handle = handle; 18911cb0ef41Sopenharmony_ci // _listen2 sets up the listened handle, it is still named like this 18921cb0ef41Sopenharmony_ci // to avoid breaking code that wraps this method 18931cb0ef41Sopenharmony_ci server._listen2(address, port, addressType, backlog, fd, flags); 18941cb0ef41Sopenharmony_ci } 18951cb0ef41Sopenharmony_ci} 18961cb0ef41Sopenharmony_ci 18971cb0ef41Sopenharmony_ci 18981cb0ef41Sopenharmony_ciServer.prototype.listen = function(...args) { 18991cb0ef41Sopenharmony_ci const normalized = normalizeArgs(args); 19001cb0ef41Sopenharmony_ci let options = normalized[0]; 19011cb0ef41Sopenharmony_ci const cb = normalized[1]; 19021cb0ef41Sopenharmony_ci 19031cb0ef41Sopenharmony_ci if (this._handle) { 19041cb0ef41Sopenharmony_ci throw new ERR_SERVER_ALREADY_LISTEN(); 19051cb0ef41Sopenharmony_ci } 19061cb0ef41Sopenharmony_ci 19071cb0ef41Sopenharmony_ci if (cb !== null) { 19081cb0ef41Sopenharmony_ci this.once('listening', cb); 19091cb0ef41Sopenharmony_ci } 19101cb0ef41Sopenharmony_ci const backlogFromArgs = 19111cb0ef41Sopenharmony_ci // (handle, backlog) or (path, backlog) or (port, backlog) 19121cb0ef41Sopenharmony_ci toNumber(args.length > 1 && args[1]) || 19131cb0ef41Sopenharmony_ci toNumber(args.length > 2 && args[2]); // (port, host, backlog) 19141cb0ef41Sopenharmony_ci 19151cb0ef41Sopenharmony_ci options = options._handle || options.handle || options; 19161cb0ef41Sopenharmony_ci const flags = getFlags(options.ipv6Only); 19171cb0ef41Sopenharmony_ci // (handle[, backlog][, cb]) where handle is an object with a handle 19181cb0ef41Sopenharmony_ci if (options instanceof TCP) { 19191cb0ef41Sopenharmony_ci this._handle = options; 19201cb0ef41Sopenharmony_ci this[async_id_symbol] = this._handle.getAsyncId(); 19211cb0ef41Sopenharmony_ci listenInCluster(this, null, -1, -1, backlogFromArgs); 19221cb0ef41Sopenharmony_ci return this; 19231cb0ef41Sopenharmony_ci } 19241cb0ef41Sopenharmony_ci addAbortSignalOption(this, options); 19251cb0ef41Sopenharmony_ci // (handle[, backlog][, cb]) where handle is an object with a fd 19261cb0ef41Sopenharmony_ci if (typeof options.fd === 'number' && options.fd >= 0) { 19271cb0ef41Sopenharmony_ci listenInCluster(this, null, null, null, backlogFromArgs, options.fd); 19281cb0ef41Sopenharmony_ci return this; 19291cb0ef41Sopenharmony_ci } 19301cb0ef41Sopenharmony_ci 19311cb0ef41Sopenharmony_ci // ([port][, host][, backlog][, cb]) where port is omitted, 19321cb0ef41Sopenharmony_ci // that is, listen(), listen(null), listen(cb), or listen(null, cb) 19331cb0ef41Sopenharmony_ci // or (options[, cb]) where options.port is explicitly set as undefined or 19341cb0ef41Sopenharmony_ci // null, bind to an arbitrary unused port 19351cb0ef41Sopenharmony_ci if (args.length === 0 || typeof args[0] === 'function' || 19361cb0ef41Sopenharmony_ci (typeof options.port === 'undefined' && 'port' in options) || 19371cb0ef41Sopenharmony_ci options.port === null) { 19381cb0ef41Sopenharmony_ci options.port = 0; 19391cb0ef41Sopenharmony_ci } 19401cb0ef41Sopenharmony_ci // ([port][, host][, backlog][, cb]) where port is specified 19411cb0ef41Sopenharmony_ci // or (options[, cb]) where options.port is specified 19421cb0ef41Sopenharmony_ci // or if options.port is normalized as 0 before 19431cb0ef41Sopenharmony_ci let backlog; 19441cb0ef41Sopenharmony_ci if (typeof options.port === 'number' || typeof options.port === 'string') { 19451cb0ef41Sopenharmony_ci validatePort(options.port, 'options.port'); 19461cb0ef41Sopenharmony_ci backlog = options.backlog || backlogFromArgs; 19471cb0ef41Sopenharmony_ci // start TCP server listening on host:port 19481cb0ef41Sopenharmony_ci if (options.host) { 19491cb0ef41Sopenharmony_ci lookupAndListen(this, options.port | 0, options.host, backlog, 19501cb0ef41Sopenharmony_ci options.exclusive, flags); 19511cb0ef41Sopenharmony_ci } else { // Undefined host, listens on unspecified address 19521cb0ef41Sopenharmony_ci // Default addressType 4 will be used to search for primary server 19531cb0ef41Sopenharmony_ci listenInCluster(this, null, options.port | 0, 4, 19541cb0ef41Sopenharmony_ci backlog, undefined, options.exclusive); 19551cb0ef41Sopenharmony_ci } 19561cb0ef41Sopenharmony_ci return this; 19571cb0ef41Sopenharmony_ci } 19581cb0ef41Sopenharmony_ci 19591cb0ef41Sopenharmony_ci // (path[, backlog][, cb]) or (options[, cb]) 19601cb0ef41Sopenharmony_ci // where path or options.path is a UNIX domain socket or Windows pipe 19611cb0ef41Sopenharmony_ci if (options.path && isPipeName(options.path)) { 19621cb0ef41Sopenharmony_ci const pipeName = this._pipeName = options.path; 19631cb0ef41Sopenharmony_ci backlog = options.backlog || backlogFromArgs; 19641cb0ef41Sopenharmony_ci listenInCluster(this, 19651cb0ef41Sopenharmony_ci pipeName, 19661cb0ef41Sopenharmony_ci -1, 19671cb0ef41Sopenharmony_ci -1, 19681cb0ef41Sopenharmony_ci backlog, 19691cb0ef41Sopenharmony_ci undefined, 19701cb0ef41Sopenharmony_ci options.exclusive, 19711cb0ef41Sopenharmony_ci undefined, 19721cb0ef41Sopenharmony_ci { 19731cb0ef41Sopenharmony_ci readableAll: options.readableAll, 19741cb0ef41Sopenharmony_ci writableAll: options.writableAll, 19751cb0ef41Sopenharmony_ci }); 19761cb0ef41Sopenharmony_ci 19771cb0ef41Sopenharmony_ci if (!this._handle) { 19781cb0ef41Sopenharmony_ci // Failed and an error shall be emitted in the next tick. 19791cb0ef41Sopenharmony_ci // Therefore, we directly return. 19801cb0ef41Sopenharmony_ci return this; 19811cb0ef41Sopenharmony_ci } 19821cb0ef41Sopenharmony_ci 19831cb0ef41Sopenharmony_ci let mode = 0; 19841cb0ef41Sopenharmony_ci if (options.readableAll === true) 19851cb0ef41Sopenharmony_ci mode |= PipeConstants.UV_READABLE; 19861cb0ef41Sopenharmony_ci if (options.writableAll === true) 19871cb0ef41Sopenharmony_ci mode |= PipeConstants.UV_WRITABLE; 19881cb0ef41Sopenharmony_ci if (mode !== 0) { 19891cb0ef41Sopenharmony_ci const err = this._handle.fchmod(mode); 19901cb0ef41Sopenharmony_ci if (err) { 19911cb0ef41Sopenharmony_ci this._handle.close(); 19921cb0ef41Sopenharmony_ci this._handle = null; 19931cb0ef41Sopenharmony_ci throw errnoException(err, 'uv_pipe_chmod'); 19941cb0ef41Sopenharmony_ci } 19951cb0ef41Sopenharmony_ci } 19961cb0ef41Sopenharmony_ci return this; 19971cb0ef41Sopenharmony_ci } 19981cb0ef41Sopenharmony_ci 19991cb0ef41Sopenharmony_ci if (!(('port' in options) || ('path' in options))) { 20001cb0ef41Sopenharmony_ci throw new ERR_INVALID_ARG_VALUE('options', options, 20011cb0ef41Sopenharmony_ci 'must have the property "port" or "path"'); 20021cb0ef41Sopenharmony_ci } 20031cb0ef41Sopenharmony_ci 20041cb0ef41Sopenharmony_ci throw new ERR_INVALID_ARG_VALUE('options', options); 20051cb0ef41Sopenharmony_ci}; 20061cb0ef41Sopenharmony_ci 20071cb0ef41Sopenharmony_cifunction lookupAndListen(self, port, address, backlog, exclusive, flags) { 20081cb0ef41Sopenharmony_ci if (dns === undefined) dns = require('dns'); 20091cb0ef41Sopenharmony_ci dns.lookup(address, function doListen(err, ip, addressType) { 20101cb0ef41Sopenharmony_ci if (err) { 20111cb0ef41Sopenharmony_ci self.emit('error', err); 20121cb0ef41Sopenharmony_ci } else { 20131cb0ef41Sopenharmony_ci addressType = ip ? addressType : 4; 20141cb0ef41Sopenharmony_ci listenInCluster(self, ip, port, addressType, 20151cb0ef41Sopenharmony_ci backlog, undefined, exclusive, flags); 20161cb0ef41Sopenharmony_ci } 20171cb0ef41Sopenharmony_ci }); 20181cb0ef41Sopenharmony_ci} 20191cb0ef41Sopenharmony_ci 20201cb0ef41Sopenharmony_ciObjectDefineProperty(Server.prototype, 'listening', { 20211cb0ef41Sopenharmony_ci __proto__: null, 20221cb0ef41Sopenharmony_ci get: function() { 20231cb0ef41Sopenharmony_ci return !!this._handle; 20241cb0ef41Sopenharmony_ci }, 20251cb0ef41Sopenharmony_ci configurable: true, 20261cb0ef41Sopenharmony_ci enumerable: true, 20271cb0ef41Sopenharmony_ci}); 20281cb0ef41Sopenharmony_ci 20291cb0ef41Sopenharmony_ciServer.prototype.address = function() { 20301cb0ef41Sopenharmony_ci if (this._handle && this._handle.getsockname) { 20311cb0ef41Sopenharmony_ci const out = {}; 20321cb0ef41Sopenharmony_ci const err = this._handle.getsockname(out); 20331cb0ef41Sopenharmony_ci if (err) { 20341cb0ef41Sopenharmony_ci throw errnoException(err, 'address'); 20351cb0ef41Sopenharmony_ci } 20361cb0ef41Sopenharmony_ci return out; 20371cb0ef41Sopenharmony_ci } else if (this._pipeName) { 20381cb0ef41Sopenharmony_ci return this._pipeName; 20391cb0ef41Sopenharmony_ci } 20401cb0ef41Sopenharmony_ci return null; 20411cb0ef41Sopenharmony_ci}; 20421cb0ef41Sopenharmony_ci 20431cb0ef41Sopenharmony_cifunction onconnection(err, clientHandle) { 20441cb0ef41Sopenharmony_ci const handle = this; 20451cb0ef41Sopenharmony_ci const self = handle[owner_symbol]; 20461cb0ef41Sopenharmony_ci 20471cb0ef41Sopenharmony_ci debug('onconnection'); 20481cb0ef41Sopenharmony_ci 20491cb0ef41Sopenharmony_ci if (err) { 20501cb0ef41Sopenharmony_ci self.emit('error', errnoException(err, 'accept')); 20511cb0ef41Sopenharmony_ci return; 20521cb0ef41Sopenharmony_ci } 20531cb0ef41Sopenharmony_ci 20541cb0ef41Sopenharmony_ci if (self.maxConnections && self._connections >= self.maxConnections) { 20551cb0ef41Sopenharmony_ci if (clientHandle.getsockname || clientHandle.getpeername) { 20561cb0ef41Sopenharmony_ci const data = ObjectCreate(null); 20571cb0ef41Sopenharmony_ci if (clientHandle.getsockname) { 20581cb0ef41Sopenharmony_ci const localInfo = ObjectCreate(null); 20591cb0ef41Sopenharmony_ci clientHandle.getsockname(localInfo); 20601cb0ef41Sopenharmony_ci data.localAddress = localInfo.address; 20611cb0ef41Sopenharmony_ci data.localPort = localInfo.port; 20621cb0ef41Sopenharmony_ci data.localFamily = localInfo.family; 20631cb0ef41Sopenharmony_ci } 20641cb0ef41Sopenharmony_ci if (clientHandle.getpeername) { 20651cb0ef41Sopenharmony_ci const remoteInfo = ObjectCreate(null); 20661cb0ef41Sopenharmony_ci clientHandle.getpeername(remoteInfo); 20671cb0ef41Sopenharmony_ci data.remoteAddress = remoteInfo.address; 20681cb0ef41Sopenharmony_ci data.remotePort = remoteInfo.port; 20691cb0ef41Sopenharmony_ci data.remoteFamily = remoteInfo.family; 20701cb0ef41Sopenharmony_ci } 20711cb0ef41Sopenharmony_ci self.emit('drop', data); 20721cb0ef41Sopenharmony_ci } else { 20731cb0ef41Sopenharmony_ci self.emit('drop'); 20741cb0ef41Sopenharmony_ci } 20751cb0ef41Sopenharmony_ci clientHandle.close(); 20761cb0ef41Sopenharmony_ci return; 20771cb0ef41Sopenharmony_ci } 20781cb0ef41Sopenharmony_ci 20791cb0ef41Sopenharmony_ci const socket = new Socket({ 20801cb0ef41Sopenharmony_ci handle: clientHandle, 20811cb0ef41Sopenharmony_ci allowHalfOpen: self.allowHalfOpen, 20821cb0ef41Sopenharmony_ci pauseOnCreate: self.pauseOnConnect, 20831cb0ef41Sopenharmony_ci readable: true, 20841cb0ef41Sopenharmony_ci writable: true, 20851cb0ef41Sopenharmony_ci readableHighWaterMark: self.highWaterMark, 20861cb0ef41Sopenharmony_ci writableHighWaterMark: self.highWaterMark, 20871cb0ef41Sopenharmony_ci }); 20881cb0ef41Sopenharmony_ci 20891cb0ef41Sopenharmony_ci if (self.noDelay && clientHandle.setNoDelay) { 20901cb0ef41Sopenharmony_ci socket[kSetNoDelay] = true; 20911cb0ef41Sopenharmony_ci clientHandle.setNoDelay(true); 20921cb0ef41Sopenharmony_ci } 20931cb0ef41Sopenharmony_ci if (self.keepAlive && clientHandle.setKeepAlive) { 20941cb0ef41Sopenharmony_ci socket[kSetKeepAlive] = true; 20951cb0ef41Sopenharmony_ci socket[kSetKeepAliveInitialDelay] = self.keepAliveInitialDelay; 20961cb0ef41Sopenharmony_ci clientHandle.setKeepAlive(true, self.keepAliveInitialDelay); 20971cb0ef41Sopenharmony_ci } 20981cb0ef41Sopenharmony_ci 20991cb0ef41Sopenharmony_ci self._connections++; 21001cb0ef41Sopenharmony_ci socket.server = self; 21011cb0ef41Sopenharmony_ci socket._server = self; 21021cb0ef41Sopenharmony_ci 21031cb0ef41Sopenharmony_ci DTRACE_NET_SERVER_CONNECTION(socket); 21041cb0ef41Sopenharmony_ci self.emit('connection', socket); 21051cb0ef41Sopenharmony_ci lazyChannels(); 21061cb0ef41Sopenharmony_ci if (netServerSocketChannel.hasSubscribers) { 21071cb0ef41Sopenharmony_ci netServerSocketChannel.publish({ 21081cb0ef41Sopenharmony_ci socket, 21091cb0ef41Sopenharmony_ci }); 21101cb0ef41Sopenharmony_ci } 21111cb0ef41Sopenharmony_ci} 21121cb0ef41Sopenharmony_ci 21131cb0ef41Sopenharmony_ci/** 21141cb0ef41Sopenharmony_ci * Gets the number of concurrent connections on the server 21151cb0ef41Sopenharmony_ci * @param {Function} cb 21161cb0ef41Sopenharmony_ci * @returns {Server} 21171cb0ef41Sopenharmony_ci */ 21181cb0ef41Sopenharmony_ci 21191cb0ef41Sopenharmony_ciServer.prototype.getConnections = function(cb) { 21201cb0ef41Sopenharmony_ci const self = this; 21211cb0ef41Sopenharmony_ci 21221cb0ef41Sopenharmony_ci function end(err, connections) { 21231cb0ef41Sopenharmony_ci defaultTriggerAsyncIdScope(self[async_id_symbol], 21241cb0ef41Sopenharmony_ci process.nextTick, 21251cb0ef41Sopenharmony_ci cb, 21261cb0ef41Sopenharmony_ci err, 21271cb0ef41Sopenharmony_ci connections); 21281cb0ef41Sopenharmony_ci } 21291cb0ef41Sopenharmony_ci 21301cb0ef41Sopenharmony_ci if (!this._usingWorkers) { 21311cb0ef41Sopenharmony_ci end(null, this._connections); 21321cb0ef41Sopenharmony_ci return this; 21331cb0ef41Sopenharmony_ci } 21341cb0ef41Sopenharmony_ci 21351cb0ef41Sopenharmony_ci // Poll workers 21361cb0ef41Sopenharmony_ci let left = this._workers.length; 21371cb0ef41Sopenharmony_ci let total = this._connections; 21381cb0ef41Sopenharmony_ci 21391cb0ef41Sopenharmony_ci function oncount(err, count) { 21401cb0ef41Sopenharmony_ci if (err) { 21411cb0ef41Sopenharmony_ci left = -1; 21421cb0ef41Sopenharmony_ci return end(err); 21431cb0ef41Sopenharmony_ci } 21441cb0ef41Sopenharmony_ci 21451cb0ef41Sopenharmony_ci total += count; 21461cb0ef41Sopenharmony_ci if (--left === 0) return end(null, total); 21471cb0ef41Sopenharmony_ci } 21481cb0ef41Sopenharmony_ci 21491cb0ef41Sopenharmony_ci for (let n = 0; n < this._workers.length; n++) { 21501cb0ef41Sopenharmony_ci this._workers[n].getConnections(oncount); 21511cb0ef41Sopenharmony_ci } 21521cb0ef41Sopenharmony_ci 21531cb0ef41Sopenharmony_ci return this; 21541cb0ef41Sopenharmony_ci}; 21551cb0ef41Sopenharmony_ci 21561cb0ef41Sopenharmony_ci 21571cb0ef41Sopenharmony_ciServer.prototype.close = function(cb) { 21581cb0ef41Sopenharmony_ci if (typeof cb === 'function') { 21591cb0ef41Sopenharmony_ci if (!this._handle) { 21601cb0ef41Sopenharmony_ci this.once('close', function close() { 21611cb0ef41Sopenharmony_ci cb(new ERR_SERVER_NOT_RUNNING()); 21621cb0ef41Sopenharmony_ci }); 21631cb0ef41Sopenharmony_ci } else { 21641cb0ef41Sopenharmony_ci this.once('close', cb); 21651cb0ef41Sopenharmony_ci } 21661cb0ef41Sopenharmony_ci } 21671cb0ef41Sopenharmony_ci 21681cb0ef41Sopenharmony_ci if (this._handle) { 21691cb0ef41Sopenharmony_ci this._handle.close(); 21701cb0ef41Sopenharmony_ci this._handle = null; 21711cb0ef41Sopenharmony_ci } 21721cb0ef41Sopenharmony_ci 21731cb0ef41Sopenharmony_ci if (this._usingWorkers) { 21741cb0ef41Sopenharmony_ci let left = this._workers.length; 21751cb0ef41Sopenharmony_ci const onWorkerClose = () => { 21761cb0ef41Sopenharmony_ci if (--left !== 0) return; 21771cb0ef41Sopenharmony_ci 21781cb0ef41Sopenharmony_ci this._connections = 0; 21791cb0ef41Sopenharmony_ci this._emitCloseIfDrained(); 21801cb0ef41Sopenharmony_ci }; 21811cb0ef41Sopenharmony_ci 21821cb0ef41Sopenharmony_ci // Increment connections to be sure that, even if all sockets will be closed 21831cb0ef41Sopenharmony_ci // during polling of workers, `close` event will be emitted only once. 21841cb0ef41Sopenharmony_ci this._connections++; 21851cb0ef41Sopenharmony_ci 21861cb0ef41Sopenharmony_ci // Poll workers 21871cb0ef41Sopenharmony_ci for (let n = 0; n < this._workers.length; n++) 21881cb0ef41Sopenharmony_ci this._workers[n].close(onWorkerClose); 21891cb0ef41Sopenharmony_ci } else { 21901cb0ef41Sopenharmony_ci this._emitCloseIfDrained(); 21911cb0ef41Sopenharmony_ci } 21921cb0ef41Sopenharmony_ci 21931cb0ef41Sopenharmony_ci return this; 21941cb0ef41Sopenharmony_ci}; 21951cb0ef41Sopenharmony_ci 21961cb0ef41Sopenharmony_ciServer.prototype[SymbolAsyncDispose] = async function() { 21971cb0ef41Sopenharmony_ci if (!this._handle) { 21981cb0ef41Sopenharmony_ci return; 21991cb0ef41Sopenharmony_ci } 22001cb0ef41Sopenharmony_ci return FunctionPrototypeCall(promisify(this.close), this); 22011cb0ef41Sopenharmony_ci}; 22021cb0ef41Sopenharmony_ci 22031cb0ef41Sopenharmony_ciServer.prototype._emitCloseIfDrained = function() { 22041cb0ef41Sopenharmony_ci debug('SERVER _emitCloseIfDrained'); 22051cb0ef41Sopenharmony_ci 22061cb0ef41Sopenharmony_ci if (this._handle || this._connections) { 22071cb0ef41Sopenharmony_ci debug('SERVER handle? %j connections? %d', 22081cb0ef41Sopenharmony_ci !!this._handle, this._connections); 22091cb0ef41Sopenharmony_ci return; 22101cb0ef41Sopenharmony_ci } 22111cb0ef41Sopenharmony_ci 22121cb0ef41Sopenharmony_ci defaultTriggerAsyncIdScope(this[async_id_symbol], 22131cb0ef41Sopenharmony_ci process.nextTick, 22141cb0ef41Sopenharmony_ci emitCloseNT, 22151cb0ef41Sopenharmony_ci this); 22161cb0ef41Sopenharmony_ci}; 22171cb0ef41Sopenharmony_ci 22181cb0ef41Sopenharmony_ci 22191cb0ef41Sopenharmony_cifunction emitCloseNT(self) { 22201cb0ef41Sopenharmony_ci debug('SERVER: emit close'); 22211cb0ef41Sopenharmony_ci self.emit('close'); 22221cb0ef41Sopenharmony_ci} 22231cb0ef41Sopenharmony_ci 22241cb0ef41Sopenharmony_ci 22251cb0ef41Sopenharmony_ciServer.prototype[EventEmitter.captureRejectionSymbol] = function( 22261cb0ef41Sopenharmony_ci err, event, sock) { 22271cb0ef41Sopenharmony_ci 22281cb0ef41Sopenharmony_ci switch (event) { 22291cb0ef41Sopenharmony_ci case 'connection': 22301cb0ef41Sopenharmony_ci sock.destroy(err); 22311cb0ef41Sopenharmony_ci break; 22321cb0ef41Sopenharmony_ci default: 22331cb0ef41Sopenharmony_ci this.emit('error', err); 22341cb0ef41Sopenharmony_ci } 22351cb0ef41Sopenharmony_ci}; 22361cb0ef41Sopenharmony_ci 22371cb0ef41Sopenharmony_ci 22381cb0ef41Sopenharmony_ci// Legacy alias on the C++ wrapper object. This is not public API, so we may 22391cb0ef41Sopenharmony_ci// want to runtime-deprecate it at some point. There's no hurry, though. 22401cb0ef41Sopenharmony_ciObjectDefineProperty(TCP.prototype, 'owner', { 22411cb0ef41Sopenharmony_ci __proto__: null, 22421cb0ef41Sopenharmony_ci get() { return this[owner_symbol]; }, 22431cb0ef41Sopenharmony_ci set(v) { return this[owner_symbol] = v; }, 22441cb0ef41Sopenharmony_ci}); 22451cb0ef41Sopenharmony_ci 22461cb0ef41Sopenharmony_ciObjectDefineProperty(Socket.prototype, '_handle', { 22471cb0ef41Sopenharmony_ci __proto__: null, 22481cb0ef41Sopenharmony_ci get() { return this[kHandle]; }, 22491cb0ef41Sopenharmony_ci set(v) { return this[kHandle] = v; }, 22501cb0ef41Sopenharmony_ci}); 22511cb0ef41Sopenharmony_ci 22521cb0ef41Sopenharmony_ciServer.prototype._setupWorker = function(socketList) { 22531cb0ef41Sopenharmony_ci this._usingWorkers = true; 22541cb0ef41Sopenharmony_ci this._workers.push(socketList); 22551cb0ef41Sopenharmony_ci socketList.once('exit', (socketList) => { 22561cb0ef41Sopenharmony_ci const index = ArrayPrototypeIndexOf(this._workers, socketList); 22571cb0ef41Sopenharmony_ci this._workers.splice(index, 1); 22581cb0ef41Sopenharmony_ci }); 22591cb0ef41Sopenharmony_ci}; 22601cb0ef41Sopenharmony_ci 22611cb0ef41Sopenharmony_ciServer.prototype.ref = function() { 22621cb0ef41Sopenharmony_ci this._unref = false; 22631cb0ef41Sopenharmony_ci 22641cb0ef41Sopenharmony_ci if (this._handle) 22651cb0ef41Sopenharmony_ci this._handle.ref(); 22661cb0ef41Sopenharmony_ci 22671cb0ef41Sopenharmony_ci return this; 22681cb0ef41Sopenharmony_ci}; 22691cb0ef41Sopenharmony_ci 22701cb0ef41Sopenharmony_ciServer.prototype.unref = function() { 22711cb0ef41Sopenharmony_ci this._unref = true; 22721cb0ef41Sopenharmony_ci 22731cb0ef41Sopenharmony_ci if (this._handle) 22741cb0ef41Sopenharmony_ci this._handle.unref(); 22751cb0ef41Sopenharmony_ci 22761cb0ef41Sopenharmony_ci return this; 22771cb0ef41Sopenharmony_ci}; 22781cb0ef41Sopenharmony_ci 22791cb0ef41Sopenharmony_cilet _setSimultaneousAccepts; 22801cb0ef41Sopenharmony_cilet warnSimultaneousAccepts = true; 22811cb0ef41Sopenharmony_ci 22821cb0ef41Sopenharmony_ciif (isWindows) { 22831cb0ef41Sopenharmony_ci let simultaneousAccepts; 22841cb0ef41Sopenharmony_ci 22851cb0ef41Sopenharmony_ci _setSimultaneousAccepts = function(handle) { 22861cb0ef41Sopenharmony_ci if (warnSimultaneousAccepts) { 22871cb0ef41Sopenharmony_ci process.emitWarning( 22881cb0ef41Sopenharmony_ci 'net._setSimultaneousAccepts() is deprecated and will be removed.', 22891cb0ef41Sopenharmony_ci 'DeprecationWarning', 'DEP0121'); 22901cb0ef41Sopenharmony_ci warnSimultaneousAccepts = false; 22911cb0ef41Sopenharmony_ci } 22921cb0ef41Sopenharmony_ci if (handle === undefined) { 22931cb0ef41Sopenharmony_ci return; 22941cb0ef41Sopenharmony_ci } 22951cb0ef41Sopenharmony_ci 22961cb0ef41Sopenharmony_ci if (simultaneousAccepts === undefined) { 22971cb0ef41Sopenharmony_ci simultaneousAccepts = (process.env.NODE_MANY_ACCEPTS && 22981cb0ef41Sopenharmony_ci process.env.NODE_MANY_ACCEPTS !== '0'); 22991cb0ef41Sopenharmony_ci } 23001cb0ef41Sopenharmony_ci 23011cb0ef41Sopenharmony_ci if (handle._simultaneousAccepts !== simultaneousAccepts) { 23021cb0ef41Sopenharmony_ci handle.setSimultaneousAccepts(!!simultaneousAccepts); 23031cb0ef41Sopenharmony_ci handle._simultaneousAccepts = simultaneousAccepts; 23041cb0ef41Sopenharmony_ci } 23051cb0ef41Sopenharmony_ci }; 23061cb0ef41Sopenharmony_ci} else { 23071cb0ef41Sopenharmony_ci _setSimultaneousAccepts = function() { 23081cb0ef41Sopenharmony_ci if (warnSimultaneousAccepts) { 23091cb0ef41Sopenharmony_ci process.emitWarning( 23101cb0ef41Sopenharmony_ci 'net._setSimultaneousAccepts() is deprecated and will be removed.', 23111cb0ef41Sopenharmony_ci 'DeprecationWarning', 'DEP0121'); 23121cb0ef41Sopenharmony_ci warnSimultaneousAccepts = false; 23131cb0ef41Sopenharmony_ci } 23141cb0ef41Sopenharmony_ci }; 23151cb0ef41Sopenharmony_ci} 23161cb0ef41Sopenharmony_ci 23171cb0ef41Sopenharmony_cimodule.exports = { 23181cb0ef41Sopenharmony_ci _createServerHandle: createServerHandle, 23191cb0ef41Sopenharmony_ci _normalizeArgs: normalizeArgs, 23201cb0ef41Sopenharmony_ci _setSimultaneousAccepts, 23211cb0ef41Sopenharmony_ci get BlockList() { 23221cb0ef41Sopenharmony_ci BlockList ??= require('internal/blocklist').BlockList; 23231cb0ef41Sopenharmony_ci return BlockList; 23241cb0ef41Sopenharmony_ci }, 23251cb0ef41Sopenharmony_ci get SocketAddress() { 23261cb0ef41Sopenharmony_ci SocketAddress ??= require('internal/socketaddress').SocketAddress; 23271cb0ef41Sopenharmony_ci return SocketAddress; 23281cb0ef41Sopenharmony_ci }, 23291cb0ef41Sopenharmony_ci connect, 23301cb0ef41Sopenharmony_ci createConnection: connect, 23311cb0ef41Sopenharmony_ci createServer, 23321cb0ef41Sopenharmony_ci isIP: isIP, 23331cb0ef41Sopenharmony_ci isIPv4: isIPv4, 23341cb0ef41Sopenharmony_ci isIPv6: isIPv6, 23351cb0ef41Sopenharmony_ci Server, 23361cb0ef41Sopenharmony_ci Socket, 23371cb0ef41Sopenharmony_ci Stream: Socket, // Legacy naming 23381cb0ef41Sopenharmony_ci getDefaultAutoSelectFamily, 23391cb0ef41Sopenharmony_ci setDefaultAutoSelectFamily, 23401cb0ef41Sopenharmony_ci getDefaultAutoSelectFamilyAttemptTimeout, 23411cb0ef41Sopenharmony_ci setDefaultAutoSelectFamilyAttemptTimeout, 23421cb0ef41Sopenharmony_ci}; 2343