fix(PortProxy): Refactor connection tracking to utilize unified records in PortProxy
This commit is contained in:
parent
3de35f3b2c
commit
a53e6f1019
@ -1,5 +1,12 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-02-23 - 3.10.4 - fix(PortProxy)
|
||||
Refactor connection tracking to utilize unified records in PortProxy
|
||||
|
||||
- Implemented a unified record system for tracking incoming and outgoing connections.
|
||||
- Replaced individual connection tracking sets with a Set of IConnectionRecord.
|
||||
- Improved logging of connection activities and statistics.
|
||||
|
||||
## 2025-02-23 - 3.10.3 - fix(PortProxy)
|
||||
Refactor and optimize PortProxy for improved readability and maintainability
|
||||
|
||||
|
@ -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)}`
|
||||
|
Loading…
x
Reference in New Issue
Block a user