update
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"expiryDate": "2025-10-19T23:55:27.838Z",
|
"expiryDate": "2025-10-20T10:10:52.985Z",
|
||||||
"issueDate": "2025-07-21T23:55:27.838Z",
|
"issueDate": "2025-07-22T10:10:52.985Z",
|
||||||
"savedAt": "2025-07-21T23:55:27.838Z"
|
"savedAt": "2025-07-22T10:10:52.986Z"
|
||||||
}
|
}
|
286
test/test.connection-stability.ts
Normal file
286
test/test.connection-stability.ts
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||||
|
import * as smartproxy from '../ts/index.js';
|
||||||
|
import * as net from 'net';
|
||||||
|
import * as crypto from 'crypto';
|
||||||
|
|
||||||
|
tap.test('Connection Stability - Fragment Cleanup', async () => {
|
||||||
|
// Create a simple TCP server
|
||||||
|
const server = net.createServer();
|
||||||
|
await new Promise<void>((resolve) => {
|
||||||
|
server.listen(0, '127.0.0.1', () => resolve());
|
||||||
|
});
|
||||||
|
const serverPort = (server.address() as net.AddressInfo).port;
|
||||||
|
|
||||||
|
// Configure a route
|
||||||
|
const routes: smartproxy.IRouteConfig[] = [{
|
||||||
|
match: {
|
||||||
|
ports: 9000,
|
||||||
|
domains: '*'
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: {
|
||||||
|
host: '127.0.0.1',
|
||||||
|
port: serverPort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
// Create SmartProxy instance with routes
|
||||||
|
const proxy = new smartproxy.SmartProxy({
|
||||||
|
keepAliveTimeoutMs: 5000,
|
||||||
|
routes
|
||||||
|
});
|
||||||
|
|
||||||
|
await proxy.start();
|
||||||
|
|
||||||
|
// Test 1: Send fragmented TLS hello
|
||||||
|
const tlsHello = Buffer.concat([
|
||||||
|
Buffer.from([0x16, 0x03, 0x03]), // TLS handshake, version 1.2
|
||||||
|
Buffer.from([0x00, 0x50]), // Length: 80 bytes
|
||||||
|
Buffer.from([0x01]), // ClientHello
|
||||||
|
Buffer.from([0x00, 0x00, 0x4c]), // Handshake length
|
||||||
|
Buffer.from([0x03, 0x03]), // TLS 1.2
|
||||||
|
crypto.randomBytes(32), // Random
|
||||||
|
Buffer.from([0x00]), // Session ID length
|
||||||
|
Buffer.from([0x00, 0x04]), // Cipher suites length
|
||||||
|
Buffer.from([0xc0, 0x2f, 0xc0, 0x30]), // Cipher suites
|
||||||
|
Buffer.from([0x01, 0x00]), // Compression methods
|
||||||
|
Buffer.from([0x00, 0x1f]), // Extensions length
|
||||||
|
// SNI extension
|
||||||
|
Buffer.from([0x00, 0x00]), // Server name extension
|
||||||
|
Buffer.from([0x00, 0x1b]), // Extension length
|
||||||
|
Buffer.from([0x00, 0x19]), // Server name list length
|
||||||
|
Buffer.from([0x00]), // Host name type
|
||||||
|
Buffer.from([0x00, 0x16]), // Name length
|
||||||
|
Buffer.from('test.example.com') // Server name
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Function to check fragment manager size
|
||||||
|
const getFragmentCount = () => {
|
||||||
|
// Access the fragment manager through the singleton
|
||||||
|
const detector = (smartproxy.detection.ProtocolDetector as any).getInstance();
|
||||||
|
const tlsFragments = detector.fragmentManager.getHandler('tls');
|
||||||
|
const httpFragments = detector.fragmentManager.getHandler('http');
|
||||||
|
return tlsFragments.size + httpFragments.size;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test fragmented connections
|
||||||
|
const connections: net.Socket[] = [];
|
||||||
|
|
||||||
|
// Create multiple fragmented connections
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
|
const client = new net.Socket();
|
||||||
|
connections.push(client);
|
||||||
|
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
client.connect(9000, '127.0.0.1', () => {
|
||||||
|
// Send first fragment
|
||||||
|
client.write(tlsHello.subarray(0, 20));
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
client.on('error', reject);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give time for fragments to accumulate
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100));
|
||||||
|
|
||||||
|
// Check that fragments are being tracked
|
||||||
|
const fragmentCount = getFragmentCount();
|
||||||
|
expect(fragmentCount).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
// Send remaining fragments and close connections
|
||||||
|
for (const client of connections) {
|
||||||
|
client.write(tlsHello.subarray(20));
|
||||||
|
client.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for connections to close
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 500));
|
||||||
|
|
||||||
|
// Check that fragments are cleaned up
|
||||||
|
const finalFragmentCount = getFragmentCount();
|
||||||
|
expect(finalFragmentCount).toEqual(0);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
await proxy.stop();
|
||||||
|
server.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('Connection Stability - Memory Leak Prevention', async () => {
|
||||||
|
// Create a simple echo server
|
||||||
|
const server = net.createServer((socket) => {
|
||||||
|
socket.pipe(socket);
|
||||||
|
});
|
||||||
|
|
||||||
|
await new Promise<void>((resolve) => {
|
||||||
|
server.listen(0, '127.0.0.1', () => resolve());
|
||||||
|
});
|
||||||
|
const serverPort = (server.address() as net.AddressInfo).port;
|
||||||
|
|
||||||
|
// Configure a route
|
||||||
|
const routes: smartproxy.IRouteConfig[] = [{
|
||||||
|
match: {
|
||||||
|
ports: 9001,
|
||||||
|
domains: '*'
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: {
|
||||||
|
host: '127.0.0.1',
|
||||||
|
port: serverPort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
// Create SmartProxy instance with routes
|
||||||
|
const proxy = new smartproxy.SmartProxy({
|
||||||
|
keepAliveTimeoutMs: 5000,
|
||||||
|
routes
|
||||||
|
});
|
||||||
|
|
||||||
|
await proxy.start();
|
||||||
|
|
||||||
|
// Function to get active connection count
|
||||||
|
const getConnectionCount = () => {
|
||||||
|
const connectionManager = (proxy as any).connectionManager;
|
||||||
|
return connectionManager.getActiveConnectionCount();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create many short-lived connections
|
||||||
|
const connectionPromises: Promise<void>[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
const promise = new Promise<void>((resolve, reject) => {
|
||||||
|
const client = new net.Socket();
|
||||||
|
|
||||||
|
client.connect(9001, '127.0.0.1', () => {
|
||||||
|
// Send some data
|
||||||
|
client.write('Hello World');
|
||||||
|
|
||||||
|
// Close after a short delay
|
||||||
|
setTimeout(() => {
|
||||||
|
client.end();
|
||||||
|
}, 50);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('close', () => resolve());
|
||||||
|
client.on('error', reject);
|
||||||
|
});
|
||||||
|
|
||||||
|
connectionPromises.push(promise);
|
||||||
|
|
||||||
|
// Stagger connection creation
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for all connections to complete
|
||||||
|
await Promise.all(connectionPromises);
|
||||||
|
|
||||||
|
// Give time for cleanup
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
|
|
||||||
|
// Check that all connections are cleaned up
|
||||||
|
const finalConnectionCount = getConnectionCount();
|
||||||
|
expect(finalConnectionCount).toEqual(0);
|
||||||
|
|
||||||
|
// Check fragment cleanup
|
||||||
|
const fragmentCount = (() => {
|
||||||
|
const detector = (smartproxy.detection.ProtocolDetector as any).getInstance();
|
||||||
|
const tlsFragments = detector.fragmentManager.getHandler('tls');
|
||||||
|
const httpFragments = detector.fragmentManager.getHandler('http');
|
||||||
|
return tlsFragments.size + httpFragments.size;
|
||||||
|
})();
|
||||||
|
|
||||||
|
expect(fragmentCount).toEqual(0);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
await proxy.stop();
|
||||||
|
server.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('Connection Stability - Rapid Connect/Disconnect', async () => {
|
||||||
|
// Create a server that immediately closes connections
|
||||||
|
const server = net.createServer((socket) => {
|
||||||
|
socket.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
await new Promise<void>((resolve) => {
|
||||||
|
server.listen(0, '127.0.0.1', () => resolve());
|
||||||
|
});
|
||||||
|
const serverPort = (server.address() as net.AddressInfo).port;
|
||||||
|
|
||||||
|
// Configure a route
|
||||||
|
const routes: smartproxy.IRouteConfig[] = [{
|
||||||
|
match: {
|
||||||
|
ports: 9002,
|
||||||
|
domains: '*'
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: {
|
||||||
|
host: '127.0.0.1',
|
||||||
|
port: serverPort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
// Create SmartProxy instance with routes
|
||||||
|
const proxy = new smartproxy.SmartProxy({
|
||||||
|
keepAliveTimeoutMs: 5000,
|
||||||
|
routes
|
||||||
|
});
|
||||||
|
|
||||||
|
await proxy.start();
|
||||||
|
|
||||||
|
let errors = 0;
|
||||||
|
const connections: Promise<void>[] = [];
|
||||||
|
|
||||||
|
// Create many rapid connections
|
||||||
|
for (let i = 0; i < 50; i++) {
|
||||||
|
const promise = new Promise<void>((resolve) => {
|
||||||
|
const client = new net.Socket();
|
||||||
|
|
||||||
|
client.on('error', () => {
|
||||||
|
errors++;
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('close', () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
client.connect(9002, '127.0.0.1');
|
||||||
|
});
|
||||||
|
|
||||||
|
connections.push(promise);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for all to complete
|
||||||
|
await Promise.all(connections);
|
||||||
|
|
||||||
|
// Give time for cleanup
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 500));
|
||||||
|
|
||||||
|
// Check that connections are cleaned up despite rapid connect/disconnect
|
||||||
|
const connectionManager = (proxy as any).connectionManager;
|
||||||
|
const finalConnectionCount = connectionManager.getActiveConnectionCount();
|
||||||
|
expect(finalConnectionCount).toEqual(0);
|
||||||
|
|
||||||
|
// Check fragment cleanup
|
||||||
|
const fragmentCount = (() => {
|
||||||
|
const detector = (smartproxy.detection.ProtocolDetector as any).getInstance();
|
||||||
|
const tlsFragments = detector.fragmentManager.getHandler('tls');
|
||||||
|
const httpFragments = detector.fragmentManager.getHandler('http');
|
||||||
|
return tlsFragments.size + httpFragments.size;
|
||||||
|
})();
|
||||||
|
|
||||||
|
expect(fragmentCount).toEqual(0);
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
await proxy.stop();
|
||||||
|
server.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.start();
|
@@ -80,28 +80,38 @@ tap.test('Protocol Detection - Unknown Protocol', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
tap.test('Protocol Detection - Fragmented HTTP', async () => {
|
tap.test('Protocol Detection - Fragmented HTTP', async () => {
|
||||||
const connectionId = 'test-connection-1';
|
// Create connection context
|
||||||
|
const context = smartproxy.detection.ProtocolDetector.createConnectionContext({
|
||||||
|
sourceIp: '127.0.0.1',
|
||||||
|
sourcePort: 12345,
|
||||||
|
destIp: '127.0.0.1',
|
||||||
|
destPort: 80,
|
||||||
|
socketId: 'test-connection-1'
|
||||||
|
});
|
||||||
|
|
||||||
// First fragment
|
// First fragment
|
||||||
const fragment1 = Buffer.from('GET /test HT');
|
const fragment1 = Buffer.from('GET /test HT');
|
||||||
let result = await smartproxy.detection.ProtocolDetector.detectWithConnectionTracking(
|
let result = await smartproxy.detection.ProtocolDetector.detectWithContext(
|
||||||
fragment1,
|
fragment1,
|
||||||
connectionId
|
context
|
||||||
);
|
);
|
||||||
expect(result.protocol).toEqual('http');
|
expect(result.protocol).toEqual('http');
|
||||||
expect(result.isComplete).toEqual(false);
|
expect(result.isComplete).toEqual(false);
|
||||||
|
|
||||||
// Second fragment
|
// Second fragment
|
||||||
const fragment2 = Buffer.from('TP/1.1\r\nHost: example.com\r\n\r\n');
|
const fragment2 = Buffer.from('TP/1.1\r\nHost: example.com\r\n\r\n');
|
||||||
result = await smartproxy.detection.ProtocolDetector.detectWithConnectionTracking(
|
result = await smartproxy.detection.ProtocolDetector.detectWithContext(
|
||||||
fragment2,
|
fragment2,
|
||||||
connectionId
|
context
|
||||||
);
|
);
|
||||||
expect(result.protocol).toEqual('http');
|
expect(result.protocol).toEqual('http');
|
||||||
expect(result.isComplete).toEqual(true);
|
expect(result.isComplete).toEqual(true);
|
||||||
expect(result.connectionInfo.method).toEqual('GET');
|
expect(result.connectionInfo.method).toEqual('GET');
|
||||||
expect(result.connectionInfo.path).toEqual('/test');
|
expect(result.connectionInfo.path).toEqual('/test');
|
||||||
expect(result.connectionInfo.domain).toEqual('example.com');
|
expect(result.connectionInfo.domain).toEqual('example.com');
|
||||||
|
|
||||||
|
// Clean up fragments
|
||||||
|
smartproxy.detection.ProtocolDetector.cleanupConnection(context);
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('Protocol Detection - HTTP Methods', async () => {
|
tap.test('Protocol Detection - HTTP Methods', async () => {
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
// TLS detector doesn't need plugins imports
|
// TLS detector doesn't need plugins imports
|
||||||
import type { IProtocolDetector } from '../models/interfaces.js';
|
import type { IProtocolDetector } from '../models/interfaces.js';
|
||||||
import type { IDetectionResult, IDetectionOptions, IConnectionInfo } from '../models/detection-types.js';
|
import type { IDetectionResult, IDetectionOptions, IConnectionInfo } from '../models/detection-types.js';
|
||||||
import { readUInt16BE, BufferAccumulator } from '../utils/buffer-utils.js';
|
import { readUInt16BE } from '../utils/buffer-utils.js';
|
||||||
import { tlsVersionToString } from '../utils/parser-utils.js';
|
import { tlsVersionToString } from '../utils/parser-utils.js';
|
||||||
|
|
||||||
// Import from protocols
|
// Import from protocols
|
||||||
@@ -24,17 +24,6 @@ export class TlsDetector implements IProtocolDetector {
|
|||||||
*/
|
*/
|
||||||
private static readonly MIN_TLS_HEADER_SIZE = 5;
|
private static readonly MIN_TLS_HEADER_SIZE = 5;
|
||||||
|
|
||||||
/**
|
|
||||||
* Fragment tracking for incomplete handshakes
|
|
||||||
*/
|
|
||||||
private static fragmentedBuffers = new Map<string, BufferAccumulator>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create connection ID from context
|
|
||||||
*/
|
|
||||||
private createConnectionId(context: { sourceIp?: string; sourcePort?: number; destIp?: string; destPort?: number }): string {
|
|
||||||
return `${context.sourceIp || 'unknown'}:${context.sourcePort || 0}->${context.destIp || 'unknown'}:${context.destPort || 0}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detect TLS protocol from buffer
|
* Detect TLS protocol from buffer
|
||||||
@@ -224,29 +213,11 @@ export class TlsDetector implements IProtocolDetector {
|
|||||||
*/
|
*/
|
||||||
detectWithContext(
|
detectWithContext(
|
||||||
buffer: Buffer,
|
buffer: Buffer,
|
||||||
context: { sourceIp?: string; sourcePort?: number; destIp?: string; destPort?: number },
|
_context: { sourceIp?: string; sourcePort?: number; destIp?: string; destPort?: number },
|
||||||
options?: IDetectionOptions
|
options?: IDetectionOptions
|
||||||
): IDetectionResult | null {
|
): IDetectionResult | null {
|
||||||
const connectionId = this.createConnectionId(context);
|
// This method is deprecated - TLS detection should use the fragment manager
|
||||||
|
// from the parent detector system, not maintain its own fragments
|
||||||
// Get or create buffer accumulator for this connection
|
return this.detect(buffer, options);
|
||||||
let accumulator = TlsDetector.fragmentedBuffers.get(connectionId);
|
|
||||||
if (!accumulator) {
|
|
||||||
accumulator = new BufferAccumulator();
|
|
||||||
TlsDetector.fragmentedBuffers.set(connectionId, accumulator);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add new data
|
|
||||||
accumulator.append(buffer);
|
|
||||||
|
|
||||||
// Try detection on accumulated data
|
|
||||||
const result = this.detect(accumulator.getBuffer(), options);
|
|
||||||
|
|
||||||
// If detection is complete or we have too much data, clean up
|
|
||||||
if (result?.isComplete || accumulator.length() > 65536) {
|
|
||||||
TlsDetector.fragmentedBuffers.delete(connectionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -120,10 +120,28 @@ export class ProtocolDetector {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const connectionId = DetectionFragmentManager.createConnectionId(context);
|
||||||
|
|
||||||
// First peek to determine protocol type
|
// First peek to determine protocol type
|
||||||
if (this.tlsDetector.canHandle(buffer)) {
|
if (this.tlsDetector.canHandle(buffer)) {
|
||||||
const result = this.tlsDetector.detectWithContext(buffer, context, options);
|
// Handle TLS with fragment accumulation
|
||||||
|
const handler = this.fragmentManager.getHandler('tls');
|
||||||
|
const fragmentResult = handler.addFragment(connectionId, buffer);
|
||||||
|
|
||||||
|
if (fragmentResult.error) {
|
||||||
|
handler.complete(connectionId);
|
||||||
|
return {
|
||||||
|
protocol: 'unknown',
|
||||||
|
connectionInfo: { protocol: 'unknown' },
|
||||||
|
isComplete: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = this.tlsDetector.detect(fragmentResult.buffer!, options);
|
||||||
if (result) {
|
if (result) {
|
||||||
|
if (result.isComplete) {
|
||||||
|
handler.complete(connectionId);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,13 +191,25 @@ export class ProtocolDetector {
|
|||||||
/**
|
/**
|
||||||
* Clean up old connection tracking entries
|
* Clean up old connection tracking entries
|
||||||
*
|
*
|
||||||
* @param maxAge Maximum age in milliseconds (default: 30 seconds)
|
* @param _maxAge Maximum age in milliseconds (default: 30 seconds)
|
||||||
*/
|
*/
|
||||||
static cleanupConnections(maxAge: number = 30000): void {
|
static cleanupConnections(_maxAge: number = 30000): void {
|
||||||
// Cleanup is now handled internally by the fragment manager
|
// Cleanup is now handled internally by the fragment manager
|
||||||
this.getInstance().fragmentManager.cleanup();
|
this.getInstance().fragmentManager.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up fragments for a specific connection
|
||||||
|
*/
|
||||||
|
static cleanupConnection(context: IConnectionContext): void {
|
||||||
|
const instance = this.getInstance();
|
||||||
|
const connectionId = DetectionFragmentManager.createConnectionId(context);
|
||||||
|
|
||||||
|
// Clean up both TLS and HTTP fragments for this connection
|
||||||
|
instance.fragmentManager.getHandler('tls').complete(connectionId);
|
||||||
|
instance.fragmentManager.getHandler('http').complete(connectionId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract domain from connection info
|
* Extract domain from connection info
|
||||||
*/
|
*/
|
||||||
|
@@ -5,6 +5,7 @@ import { connectionLogDeduplicator } from '../../core/utils/log-deduplicator.js'
|
|||||||
import { LifecycleComponent } from '../../core/utils/lifecycle-component.js';
|
import { LifecycleComponent } from '../../core/utils/lifecycle-component.js';
|
||||||
import { cleanupSocket } from '../../core/utils/socket-utils.js';
|
import { cleanupSocket } from '../../core/utils/socket-utils.js';
|
||||||
import { WrappedSocket } from '../../core/models/wrapped-socket.js';
|
import { WrappedSocket } from '../../core/models/wrapped-socket.js';
|
||||||
|
import { ProtocolDetector } from '../../detection/index.js';
|
||||||
import type { SmartProxy } from './smart-proxy.js';
|
import type { SmartProxy } from './smart-proxy.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -323,6 +324,18 @@ export class ConnectionManager extends LifecycleComponent {
|
|||||||
this.smartProxy.metricsCollector.removeConnection(record.id);
|
this.smartProxy.metricsCollector.removeConnection(record.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean up protocol detection fragments
|
||||||
|
const context = ProtocolDetector.createConnectionContext({
|
||||||
|
sourceIp: record.remoteIP,
|
||||||
|
sourcePort: record.incoming?.remotePort || 0,
|
||||||
|
destIp: record.incoming?.localAddress || '',
|
||||||
|
destPort: record.localPort,
|
||||||
|
socketId: record.id
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clean up any pending detection fragments for this connection
|
||||||
|
ProtocolDetector.cleanupConnection(context);
|
||||||
|
|
||||||
if (record.cleanupTimer) {
|
if (record.cleanupTimer) {
|
||||||
clearTimeout(record.cleanupTimer);
|
clearTimeout(record.cleanupTimer);
|
||||||
record.cleanupTimer = undefined;
|
record.cleanupTimer = undefined;
|
||||||
|
@@ -303,18 +303,18 @@ export class RouteConnectionHandler {
|
|||||||
|
|
||||||
// Handler for processing initial data (after potential PROXY protocol)
|
// Handler for processing initial data (after potential PROXY protocol)
|
||||||
const processInitialData = async (chunk: Buffer) => {
|
const processInitialData = async (chunk: Buffer) => {
|
||||||
// Use ProtocolDetector to identify protocol
|
// Create connection context for protocol detection
|
||||||
const connectionId = ProtocolDetector.createConnectionId({
|
const context = ProtocolDetector.createConnectionContext({
|
||||||
sourceIp: record.remoteIP,
|
sourceIp: record.remoteIP,
|
||||||
sourcePort: socket.remotePort,
|
sourcePort: socket.remotePort || 0,
|
||||||
destIp: socket.localAddress,
|
destIp: socket.localAddress || '',
|
||||||
destPort: socket.localPort,
|
destPort: socket.localPort || 0,
|
||||||
socketId: record.id
|
socketId: record.id
|
||||||
});
|
});
|
||||||
|
|
||||||
const detectionResult = await ProtocolDetector.detectWithConnectionTracking(
|
const detectionResult = await ProtocolDetector.detectWithContext(
|
||||||
chunk,
|
chunk,
|
||||||
connectionId,
|
context,
|
||||||
{ extractFullHeaders: false } // Only extract essential info for routing
|
{ extractFullHeaders: false } // Only extract essential info for routing
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user