UNPKG

@push.rocks/smartproxy

Version:

A powerful proxy package that effectively handles high traffic, with features such as SSL/TLS support, port proxying, WebSocket handling, dynamic routing with authentication options, and automatic ACME certificate management.

154 lines 11.2 kB
/** * Manages timeouts and inactivity tracking for connections */ export class TimeoutManager { constructor(settings) { this.settings = settings; } /** * Ensure timeout values don't exceed Node.js max safe integer */ ensureSafeTimeout(timeout) { const MAX_SAFE_TIMEOUT = 2147483647; // Maximum safe value (2^31 - 1) return Math.min(Math.floor(timeout), MAX_SAFE_TIMEOUT); } /** * Generate a slightly randomized timeout to prevent thundering herd */ randomizeTimeout(baseTimeout, variationPercent = 5) { const safeBaseTimeout = this.ensureSafeTimeout(baseTimeout); const variation = safeBaseTimeout * (variationPercent / 100); return this.ensureSafeTimeout(safeBaseTimeout + Math.floor(Math.random() * variation * 2) - variation); } /** * Update connection activity timestamp */ updateActivity(record) { record.lastActivity = Date.now(); // Clear any inactivity warning if (record.inactivityWarningIssued) { record.inactivityWarningIssued = false; } } /** * Calculate effective inactivity timeout based on connection type */ getEffectiveInactivityTimeout(record) { let effectiveTimeout = this.settings.inactivityTimeout || 14400000; // 4 hours default // For immortal keep-alive connections, use an extremely long timeout if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal') { return Number.MAX_SAFE_INTEGER; } // For extended keep-alive connections, apply multiplier if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'extended') { const multiplier = this.settings.keepAliveInactivityMultiplier || 6; effectiveTimeout = effectiveTimeout * multiplier; } return this.ensureSafeTimeout(effectiveTimeout); } /** * Calculate effective max lifetime based on connection type */ getEffectiveMaxLifetime(record) { // Use domain-specific timeout if available const baseTimeout = record.domainConfig?.connectionTimeout || this.settings.maxConnectionLifetime || 86400000; // 24 hours default // For immortal keep-alive connections, use an extremely long lifetime if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal') { return Number.MAX_SAFE_INTEGER; } // For extended keep-alive connections, use the extended lifetime setting if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'extended') { return this.ensureSafeTimeout(this.settings.extendedKeepAliveLifetime || 7 * 24 * 60 * 60 * 1000 // 7 days default ); } // Apply randomization if enabled if (this.settings.enableRandomizedTimeouts) { return this.randomizeTimeout(baseTimeout); } return this.ensureSafeTimeout(baseTimeout); } /** * Setup connection timeout * @returns The cleanup timer */ setupConnectionTimeout(record, onTimeout) { // Clear any existing timer if (record.cleanupTimer) { clearTimeout(record.cleanupTimer); } // Calculate effective timeout const effectiveLifetime = this.getEffectiveMaxLifetime(record); // Set up the timeout const timer = setTimeout(() => { // Call the provided callback onTimeout(record, 'connection_timeout'); }, effectiveLifetime); // Make sure timeout doesn't keep the process alive if (timer.unref) { timer.unref(); } return timer; } /** * Check for inactivity on a connection * @returns Object with check results */ checkInactivity(record) { // Skip for connections with inactivity check disabled if (this.settings.disableInactivityCheck) { return { isInactive: false, shouldWarn: false, inactivityTime: 0, effectiveTimeout: 0 }; } // Skip for immortal keep-alive connections if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal') { return { isInactive: false, shouldWarn: false, inactivityTime: 0, effectiveTimeout: 0 }; } const now = Date.now(); const inactivityTime = now - record.lastActivity; const effectiveTimeout = this.getEffectiveInactivityTimeout(record); // Check if inactive const isInactive = inactivityTime > effectiveTimeout; // For keep-alive connections, we should warn first const shouldWarn = record.hasKeepAlive && isInactive && !record.inactivityWarningIssued; return { isInactive, shouldWarn, inactivityTime, effectiveTimeout }; } /** * Apply socket timeout settings */ applySocketTimeouts(record) { // Skip for immortal keep-alive connections if (record.hasKeepAlive && this.settings.keepAliveTreatment === 'immortal') { // Disable timeouts completely for immortal connections record.incoming.setTimeout(0); if (record.outgoing) { record.outgoing.setTimeout(0); } return; } // Apply normal timeouts const timeout = this.ensureSafeTimeout(this.settings.socketTimeout || 3600000); // 1 hour default record.incoming.setTimeout(timeout); if (record.outgoing) { record.outgoing.setTimeout(timeout); } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wcC50aW1lb3V0bWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3NtYXJ0cHJveHkvY2xhc3Nlcy5wcC50aW1lb3V0bWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQTs7R0FFRztBQUNILE1BQU0sT0FBTyxjQUFjO0lBQ3pCLFlBQW9CLFFBQTRCO1FBQTVCLGFBQVEsR0FBUixRQUFRLENBQW9CO0lBQUcsQ0FBQztJQUVwRDs7T0FFRztJQUNJLGlCQUFpQixDQUFDLE9BQWU7UUFDdEMsTUFBTSxnQkFBZ0IsR0FBRyxVQUFVLENBQUMsQ0FBQyxnQ0FBZ0M7UUFDckUsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxnQkFBZ0IsQ0FBQyxXQUFtQixFQUFFLG1CQUEyQixDQUFDO1FBQ3ZFLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM1RCxNQUFNLFNBQVMsR0FBRyxlQUFlLEdBQUcsQ0FBQyxnQkFBZ0IsR0FBRyxHQUFHLENBQUMsQ0FBQztRQUM3RCxPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FDM0IsZUFBZSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLFNBQVMsR0FBRyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQ3hFLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSSxjQUFjLENBQUMsTUFBeUI7UUFDN0MsTUFBTSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFFakMsK0JBQStCO1FBQy9CLElBQUksTUFBTSxDQUFDLHVCQUF1QixFQUFFLENBQUM7WUFDbkMsTUFBTSxDQUFDLHVCQUF1QixHQUFHLEtBQUssQ0FBQztRQUN6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