update
This commit is contained in:
@ -6,8 +6,9 @@
|
||||
import * as plugins from '../../../plugins.js';
|
||||
import type { IConnectionManager } from './interfaces.js';
|
||||
import type { ISessionManager } from './interfaces.js';
|
||||
import { SmtpResponseCode, SMTP_DEFAULTS } from './constants.js';
|
||||
import { SmtpResponseCode, SMTP_DEFAULTS, SmtpState } from './constants.js';
|
||||
import { SmtpLogger } from './utils/logging.js';
|
||||
import { adaptiveLogger } from './utils/adaptive-logging.js';
|
||||
import { getSocketDetails, formatMultilineResponse } from './utils/helpers.js';
|
||||
|
||||
/**
|
||||
@ -95,9 +96,9 @@ export class ConnectionManager implements IConnectionManager {
|
||||
this.sessionManager = sessionManager;
|
||||
this.commandHandler = commandHandler;
|
||||
|
||||
// Default values for resource management - adjusted for testing
|
||||
const DEFAULT_MAX_CONNECTIONS_PER_IP = 20; // Increased to allow tests with multiple connections
|
||||
const DEFAULT_CONNECTION_RATE_LIMIT = 100; // Increased for test environments
|
||||
// Default values for resource management - adjusted for production scalability
|
||||
const DEFAULT_MAX_CONNECTIONS_PER_IP = 50; // Increased to support high-concurrency scenarios
|
||||
const DEFAULT_CONNECTION_RATE_LIMIT = 200; // Increased for production load handling
|
||||
const DEFAULT_CONNECTION_RATE_WINDOW = 60 * 1000; // 60 seconds window
|
||||
const DEFAULT_BUFFER_SIZE_LIMIT = 10 * 1024 * 1024; // 10 MB
|
||||
const DEFAULT_RESOURCE_CHECK_INTERVAL = 30 * 1000; // 30 seconds
|
||||
@ -362,9 +363,12 @@ export class ConnectionManager implements IConnectionManager {
|
||||
// Create a session for this connection
|
||||
this.sessionManager.createSession(socket, false);
|
||||
|
||||
// Log the new connection
|
||||
// Log the new connection using adaptive logger
|
||||
const socketDetails = getSocketDetails(socket);
|
||||
SmtpLogger.logConnection(socket, 'connect');
|
||||
adaptiveLogger.logConnection(socket, 'connect');
|
||||
|
||||
// Update adaptive logger with current connection count
|
||||
adaptiveLogger.updateConnectionCount(this.connectionStats.activeConnections);
|
||||
|
||||
// Send greeting
|
||||
this.sendGreeting(socket);
|
||||
@ -515,8 +519,11 @@ export class ConnectionManager implements IConnectionManager {
|
||||
// Create a session for this connection
|
||||
this.sessionManager.createSession(socket, true);
|
||||
|
||||
// Log the new secure connection
|
||||
SmtpLogger.logConnection(socket, 'connect');
|
||||
// Log the new secure connection using adaptive logger
|
||||
adaptiveLogger.logConnection(socket, 'connect');
|
||||
|
||||
// Update adaptive logger with current connection count
|
||||
adaptiveLogger.updateConnectionCount(this.connectionStats.activeConnections);
|
||||
|
||||
// Send greeting
|
||||
this.sendGreeting(socket);
|
||||
@ -551,6 +558,23 @@ export class ConnectionManager implements IConnectionManager {
|
||||
this.sessionManager.updateSessionActivity(session);
|
||||
}
|
||||
|
||||
// Check if we're in DATA receiving mode - handle differently
|
||||
if (session && session.state === SmtpState.DATA_RECEIVING) {
|
||||
// In DATA mode, pass raw chunks directly to command handler with special marker
|
||||
// Don't line-buffer large email content
|
||||
try {
|
||||
const dataString = data.toString('utf8');
|
||||
// Use a special prefix to indicate this is raw data, not a command line
|
||||
this.commandHandler(socket, `__RAW_DATA__${dataString}`);
|
||||
return;
|
||||
} catch (dataError) {
|
||||
SmtpLogger.error(`Data handler error during DATA mode: ${dataError instanceof Error ? dataError.message : String(dataError)}`);
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// For command mode, continue with line-buffered processing
|
||||
// Check buffer size limits to prevent memory attacks
|
||||
totalBytesReceived += data.length;
|
||||
|
||||
@ -689,6 +713,12 @@ export class ConnectionManager implements IConnectionManager {
|
||||
|
||||
// Clear active connections
|
||||
this.activeConnections.clear();
|
||||
|
||||
// Stop resource monitoring to prevent hanging timers
|
||||
if (this.resourceCheckInterval) {
|
||||
clearInterval(this.resourceCheckInterval);
|
||||
this.resourceCheckInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -728,7 +758,10 @@ export class ConnectionManager implements IConnectionManager {
|
||||
}
|
||||
|
||||
// Log connection close with session details if available
|
||||
SmtpLogger.logConnection(socket, 'close', session);
|
||||
adaptiveLogger.logConnection(socket, 'close', session);
|
||||
|
||||
// Update adaptive logger with new connection count
|
||||
adaptiveLogger.updateConnectionCount(this.connectionStats.activeConnections);
|
||||
} catch (error) {
|
||||
// Handle any unexpected errors during cleanup
|
||||
SmtpLogger.error(`Error in handleSocketClose: ${error instanceof Error ? error.message : String(error)}`);
|
||||
@ -765,8 +798,8 @@ export class ConnectionManager implements IConnectionManager {
|
||||
remotePort: socketDetails.remotePort
|
||||
});
|
||||
|
||||
// Log the error for connection tracking
|
||||
SmtpLogger.logConnection(socket, 'error', session, error);
|
||||
// Log the error for connection tracking using adaptive logger
|
||||
adaptiveLogger.logConnection(socket, 'error', session, error);
|
||||
|
||||
// Cancel any timeout ID stored in the session
|
||||
if (session?.dataTimeoutId) {
|
||||
@ -921,7 +954,7 @@ export class ConnectionManager implements IConnectionManager {
|
||||
private sendResponse(socket: plugins.net.Socket | plugins.tls.TLSSocket, response: string): void {
|
||||
try {
|
||||
socket.write(`${response}${SMTP_DEFAULTS.CRLF}`);
|
||||
SmtpLogger.logResponse(response, socket);
|
||||
adaptiveLogger.logResponse(response, socket);
|
||||
} catch (error) {
|
||||
// Log error and destroy socket
|
||||
SmtpLogger.error(`Error sending response: ${error instanceof Error ? error.message : String(error)}`, {
|
||||
|
Reference in New Issue
Block a user