node_modules: update (#259)

Co-authored-by: dawidd6 <9713907+dawidd6@users.noreply.github.com>
This commit is contained in:
Dawid Dziurla
2026-02-05 08:49:11 +01:00
committed by GitHub
parent a4eb4faebc
commit 62a2d05b79
16 changed files with 335 additions and 131 deletions

View File

@@ -7,6 +7,7 @@
const net = require('net');
const tls = require('tls');
const urllib = require('url');
const errors = require('../errors');
/**
* Establishes proxied connection to destinationPort
@@ -121,7 +122,9 @@ function httpProxyClient(proxyUrl, destinationPort, destinationHost, callback) {
} catch (_E) {
// ignore
}
return callback(new Error('Invalid response from proxy' + ((match && ': ' + match[1]) || '')));
let err = new Error('Invalid response from proxy' + ((match && ': ' + match[1]) || ''));
err.code = errors.EPROXY;
return callback(err);
}
socket.removeListener('error', tempSocketErr);

View File

@@ -197,6 +197,17 @@ class SMTPConnection extends EventEmitter {
this._onSocketClose = () => this._onClose();
this._onSocketEnd = () => this._onEnd();
this._onSocketTimeout = () => this._onTimeout();
/**
* Connection-phase error handler (supports fallback to alternative addresses)
*/
this._onConnectionSocketError = err => this._onConnectionError(err, 'ESOCKET');
/**
* Connection attempt counter for fallback race condition protection
* @private
*/
this._connectionAttemptId = 0;
}
/**
@@ -232,18 +243,10 @@ class SMTPConnection extends EventEmitter {
opts.localAddress = this.options.localAddress;
}
let setupConnectionHandlers = () => {
this._connectionTimeout = setTimeout(() => {
this._onError('Connection timeout', 'ETIMEDOUT', false, 'CONN');
}, this.options.connectionTimeout || CONNECTION_TIMEOUT);
this._socket.on('error', this._onSocketError);
};
if (this.options.connection) {
// connection is already opened
this._socket = this.options.connection;
setupConnectionHandlers();
this._setupConnectionHandlers();
if (this.secureConnection && !this.alreadySecured) {
setImmediate(() =>
@@ -288,7 +291,7 @@ class SMTPConnection extends EventEmitter {
this._socket.setKeepAlive(true);
this._onConnect();
});
setupConnectionHandlers();
this._setupConnectionHandlers();
} catch (E) {
return setImmediate(() => this._onError(E, 'ECONNECTION', false, 'CONN'));
}
@@ -327,15 +330,12 @@ class SMTPConnection extends EventEmitter {
opts[key] = resolved[key];
}
});
try {
this._socket = tls.connect(opts, () => {
this._socket.setKeepAlive(true);
this._onConnect();
});
setupConnectionHandlers();
} catch (E) {
return setImmediate(() => this._onError(E, 'ECONNECTION', false, 'CONN'));
}
// Store fallback addresses for retry on connection failure
this._fallbackAddresses = (resolved._addresses || []).filter(addr => addr !== opts.host);
this._connectOpts = Object.assign({}, opts);
this._connectToHost(opts, true);
});
} else {
// connect using plaintext
@@ -360,19 +360,101 @@ class SMTPConnection extends EventEmitter {
opts[key] = resolved[key];
}
});
try {
this._socket = net.connect(opts, () => {
this._socket.setKeepAlive(true);
this._onConnect();
});
setupConnectionHandlers();
} catch (E) {
return setImmediate(() => this._onError(E, 'ECONNECTION', false, 'CONN'));
}
// Store fallback addresses for retry on connection failure
this._fallbackAddresses = (resolved._addresses || []).filter(addr => addr !== opts.host);
this._connectOpts = Object.assign({}, opts);
this._connectToHost(opts, false);
});
}
}
/**
* Attempts to connect to the specified host address
*
* @param {Object} opts Connection options
* @param {Boolean} secure Whether to use TLS
*/
_connectToHost(opts, secure) {
this._connectionAttemptId++;
const currentAttemptId = this._connectionAttemptId;
let connectFn = secure ? tls.connect : net.connect;
try {
this._socket = connectFn(opts, () => {
// Ignore callback if this is a stale connection attempt
if (this._connectionAttemptId !== currentAttemptId) {
return;
}
this._socket.setKeepAlive(true);
this._onConnect();
});
this._setupConnectionHandlers();
} catch (E) {
return setImmediate(() => this._onError(E, 'ECONNECTION', false, 'CONN'));
}
}
/**
* Sets up connection timeout and error handlers
*/
_setupConnectionHandlers() {
this._connectionTimeout = setTimeout(() => {
this._onConnectionError('Connection timeout', 'ETIMEDOUT');
}, this.options.connectionTimeout || CONNECTION_TIMEOUT);
this._socket.on('error', this._onConnectionSocketError);
}
/**
* Handles connection errors with fallback to alternative addresses
*
* @param {Error|String} err Error object or message
* @param {String} code Error code
*/
_onConnectionError(err, code) {
clearTimeout(this._connectionTimeout);
// Check if we have fallback addresses to try
let canFallback = this._fallbackAddresses && this._fallbackAddresses.length && this.stage === 'init' && !this._destroyed;
if (!canFallback) {
// No more fallback addresses, report the error
this._onError(err, code, false, 'CONN');
return;
}
let nextHost = this._fallbackAddresses.shift();
this.logger.info(
{
tnx: 'network',
failedHost: this._connectOpts.host,
nextHost,
error: err.message || err
},
'Connection to %s failed, trying %s',
this._connectOpts.host,
nextHost
);
// Clean up current socket
if (this._socket) {
try {
this._socket.removeListener('error', this._onConnectionSocketError);
this._socket.destroy();
} catch (_E) {
// ignore
}
this._socket = null;
}
// Update host and retry
this._connectOpts.host = nextHost;
this._connectToHost(this._connectOpts, this.secureConnection);
}
/**
* Sends QUIT
*/
@@ -414,6 +496,15 @@ class SMTPConnection extends EventEmitter {
if (socket && !socket.destroyed) {
try {
// Clear socket timeout to prevent timer leaks
socket.setTimeout(0);
// Remove all listeners to allow proper garbage collection
socket.removeListener('data', this._onSocketData);
socket.removeListener('timeout', this._onSocketTimeout);
socket.removeListener('close', this._onSocketClose);
socket.removeListener('end', this._onSocketEnd);
socket.removeListener('error', this._onSocketError);
socket.removeListener('error', this._onConnectionSocketError);
socket[closeMethod]();
} catch (_E) {
// just ignore
@@ -715,7 +806,10 @@ class SMTPConnection extends EventEmitter {
this._socket.removeListener('timeout', this._onSocketTimeout);
this._socket.removeListener('close', this._onSocketClose);
this._socket.removeListener('end', this._onSocketEnd);
// Switch from connection-phase error handler to normal error handler
this._socket.removeListener('error', this._onConnectionSocketError);
this._socket.on('error', this._onSocketError);
this._socket.on('data', this._onSocketData);
this._socket.once('close', this._onSocketClose);
this._socket.once('end', this._onSocketEnd);
@@ -941,8 +1035,10 @@ class SMTPConnection extends EventEmitter {
this.upgrading = false;
this._socket.on('data', this._onSocketData);
// Remove all listeners from the plain socket to allow proper garbage collection
socketPlain.removeListener('close', this._onSocketClose);
socketPlain.removeListener('end', this._onSocketEnd);
socketPlain.removeListener('error', this._onSocketError);
return callback(null, true);
});