fix(PortProxy): Refactor connection tracking to utilize unified records in PortProxy
This commit is contained in:
		| @@ -3,6 +3,6 @@ | ||||
|  */ | ||||
| export const commitinfo = { | ||||
|   name: '@push.rocks/smartproxy', | ||||
|   version: '3.10.3', | ||||
|   version: '3.10.4', | ||||
|   description: 'a proxy for handling high workloads of proxying' | ||||
| } | ||||
|   | ||||
| @@ -79,12 +79,19 @@ function extractSNI(buffer: Buffer): string | undefined { | ||||
|   return undefined; | ||||
| } | ||||
|  | ||||
| interface IConnectionRecord { | ||||
|   incoming: plugins.net.Socket; | ||||
|   outgoing: plugins.net.Socket | null; | ||||
|   incomingStartTime: number; | ||||
|   outgoingStartTime?: number; | ||||
|   connectionClosed: boolean; | ||||
| } | ||||
|  | ||||
| export class PortProxy { | ||||
|   netServer: plugins.net.Server; | ||||
|   settings: IProxySettings; | ||||
|   private activeConnections: Set<plugins.net.Socket> = new Set(); | ||||
|   private incomingConnectionTimes: Map<plugins.net.Socket, number> = new Map(); | ||||
|   private outgoingConnectionTimes: Map<plugins.net.Socket, number> = new Map(); | ||||
|   // Unified record tracking each connection pair. | ||||
|   private connectionRecords: Set<IConnectionRecord> = new Set(); | ||||
|   private connectionLogger: NodeJS.Timeout | null = null; | ||||
|  | ||||
|   private terminationStats: { | ||||
| @@ -140,29 +147,26 @@ export class PortProxy { | ||||
|  | ||||
|     this.netServer = plugins.net.createServer((socket: plugins.net.Socket) => { | ||||
|       const remoteIP = socket.remoteAddress || ''; | ||||
|       this.activeConnections.add(socket); | ||||
|       this.incomingConnectionTimes.set(socket, Date.now()); | ||||
|       console.log(`New connection from ${remoteIP}. Active connections: ${this.activeConnections.size}`); | ||||
|       const connectionRecord: IConnectionRecord = { | ||||
|         incoming: socket, | ||||
|         outgoing: null, | ||||
|         incomingStartTime: Date.now(), | ||||
|         connectionClosed: false, | ||||
|       }; | ||||
|       this.connectionRecords.add(connectionRecord); | ||||
|       console.log(`New connection from ${remoteIP}. Active connections: ${this.connectionRecords.size}`); | ||||
|  | ||||
|       let initialDataReceived = false; | ||||
|       let incomingTerminationReason: string | null = null; | ||||
|       let outgoingTerminationReason: string | null = null; | ||||
|       let targetSocket: plugins.net.Socket | null = null; | ||||
|       let connectionClosed = false; | ||||
|  | ||||
|       // Ensure cleanup happens only once. | ||||
|       // Ensure cleanup happens only once for the entire connection record. | ||||
|       const cleanupOnce = () => { | ||||
|         if (!connectionClosed) { | ||||
|           connectionClosed = true; | ||||
|           cleanUpSockets(socket, targetSocket || undefined); | ||||
|           this.incomingConnectionTimes.delete(socket); | ||||
|           if (targetSocket) { | ||||
|             this.outgoingConnectionTimes.delete(targetSocket); | ||||
|           } | ||||
|           if (this.activeConnections.has(socket)) { | ||||
|             this.activeConnections.delete(socket); | ||||
|             console.log(`Connection from ${remoteIP} terminated. Active connections: ${this.activeConnections.size}`); | ||||
|           } | ||||
|         if (!connectionRecord.connectionClosed) { | ||||
|           connectionRecord.connectionClosed = true; | ||||
|           cleanUpSockets(connectionRecord.incoming, connectionRecord.outgoing || undefined); | ||||
|           this.connectionRecords.delete(connectionRecord); | ||||
|           console.log(`Connection from ${remoteIP} terminated. Active connections: ${this.connectionRecords.size}`); | ||||
|         } | ||||
|       }; | ||||
|  | ||||
| @@ -242,10 +246,10 @@ export class PortProxy { | ||||
|           connectionOptions.localAddress = remoteIP.replace('::ffff:', ''); | ||||
|         } | ||||
|  | ||||
|         targetSocket = plugins.net.connect(connectionOptions); | ||||
|         if (targetSocket) { | ||||
|           this.outgoingConnectionTimes.set(targetSocket, Date.now()); | ||||
|         } | ||||
|         const targetSocket = plugins.net.connect(connectionOptions); | ||||
|         connectionRecord.outgoing = targetSocket; | ||||
|         connectionRecord.outgoingStartTime = Date.now(); | ||||
|  | ||||
|         console.log( | ||||
|           `Connection established: ${remoteIP} -> ${targetHost}:${this.settings.toPort}` + | ||||
|           `${serverName ? ` (SNI: ${serverName})` : ''}` | ||||
| @@ -314,20 +318,19 @@ export class PortProxy { | ||||
|         ); | ||||
|       }); | ||||
|  | ||||
|     // Log active connection count, longest running connection durations, | ||||
|     // and termination statistics every 10 seconds. | ||||
|     // Every 10 seconds log active connection count and longest running durations. | ||||
|     this.connectionLogger = setInterval(() => { | ||||
|       const now = Date.now(); | ||||
|       let maxIncoming = 0; | ||||
|       for (const startTime of this.incomingConnectionTimes.values()) { | ||||
|         maxIncoming = Math.max(maxIncoming, now - startTime); | ||||
|       } | ||||
|       let maxOutgoing = 0; | ||||
|       for (const startTime of this.outgoingConnectionTimes.values()) { | ||||
|         maxOutgoing = Math.max(maxOutgoing, now - startTime); | ||||
|       for (const record of this.connectionRecords) { | ||||
|         maxIncoming = Math.max(maxIncoming, now - record.incomingStartTime); | ||||
|         if (record.outgoingStartTime) { | ||||
|           maxOutgoing = Math.max(maxOutgoing, now - record.outgoingStartTime); | ||||
|         } | ||||
|       } | ||||
|       console.log( | ||||
|         `(Interval Log) Active connections: ${this.activeConnections.size}. ` + | ||||
|         `(Interval Log) Active connections: ${this.connectionRecords.size}. ` + | ||||
|         `Longest running incoming: ${plugins.prettyMs(maxIncoming)}, outgoing: ${plugins.prettyMs(maxOutgoing)}. ` + | ||||
|         `Termination stats (incoming): ${JSON.stringify(this.terminationStats.incoming)}, ` + | ||||
|         `(outgoing): ${JSON.stringify(this.terminationStats.outgoing)}` | ||||
|   | ||||
		Reference in New Issue
	
	Block a user