refactor networking

This commit is contained in:
andrei-mihnea-cerbu
2024-11-12 16:13:07 +02:00
parent 8d6e208e06
commit 4fb58b9727
13 changed files with 240 additions and 115 deletions
+25 -3
View File
@@ -18,6 +18,16 @@ export class UdpClient {
this.operationHandler.loadPlugin(new GeneralOperations());
}
// Unified logging function
private log(message: string, level: 'log' | 'error' = 'log'): void {
const prefix = '[UdpClient]';
if (level === 'error') {
console.error(`${prefix} ${message}`);
} else {
console.log(`${prefix} ${message}`);
}
}
// Send heartbeat and get clients that respond with ALIVE, excluding the host machine's IP addresses
async getAliveClients(): Promise<string[]> {
const subnet = this.getSubnet();
@@ -25,9 +35,11 @@ export class UdpClient {
// Get local machine's IP addresses to exclude
const localIPs = this.getLocalIPs();
this.log(`Local IPs to exclude from scan: ${localIPs.join(', ')}`);
// First, filter active IPs that respond to ping
const activeIps = await this.filterActiveIps(ipRange);
this.log(`Active IPs in subnet ${subnet}: ${activeIps.join(', ')}`);
// Send heartbeat to each active IP and keep only those that respond with ALIVE
const aliveClients: string[] = [];
@@ -40,7 +52,8 @@ export class UdpClient {
}
}
return aliveClients; // Return the list of IPs that responded with ALIVE, excluding the host machine
this.log(`Alive clients (excluding local machine): ${aliveClients.join(', ')}`);
return aliveClients;
}
// Get local IP addresses of the host machine (excluding loopback)
@@ -65,8 +78,10 @@ export class UdpClient {
const heartbeatCode = operationCodes.HEARTBEAT;
const heartbeatMessage = MessageHandler.formatMessage(heartbeatCode);
this.log(`Sending heartbeat to ${ip}`);
this.udpSocket.send(heartbeatMessage, this.port, ip, (err) => {
if (err) {
this.log(`Failed to send heartbeat to ${ip}: ${err.message}`, 'error');
resolve({ found: false });
} else {
const timeout = setTimeout(() => {
@@ -79,8 +94,10 @@ export class UdpClient {
clearTimeout(timeout);
const parsedMessage = MessageHandler.parseMessage(msg.toString());
if (parsedMessage?.operationCode === operationCodes.ALIVE) {
this.log(`Received ALIVE response from ${ip}`);
resolve({ found: true });
} else {
this.log(`Unexpected response from ${ip}`);
resolve({ found: false });
}
}
@@ -94,8 +111,9 @@ export class UdpClient {
private dropConnection(ip: string): void {
try {
this.udpSocket.removeAllListeners('message');
this.log(`Dropped connection listeners for ${ip}`);
} catch (err: any) {
console.error(`Error dropping connection to ${ip}: ${err.message}`);
this.log(`Error dropping connection to ${ip}: ${err.message}`, 'error');
}
}
@@ -105,7 +123,9 @@ export class UdpClient {
for (const iface of Object.values(interfaces)) {
for (const address of iface || []) {
if (address.family === 'IPv4' && !address.internal) {
return address.address.split('.').slice(0, 3).join('.');
const subnet = address.address.split('.').slice(0, 3).join('.');
this.log(`Detected subnet: ${subnet}`);
return subnet;
}
}
}
@@ -118,6 +138,7 @@ export class UdpClient {
for (let i = 1; i < 255; i++) {
ipRange.push(`${subnet}.${i}`);
}
this.log(`Generated IP range for subnet ${subnet}`);
return ipRange;
}
@@ -135,6 +156,7 @@ export class UdpClient {
}
}
this.log(`Active IPs after pinging: ${activeIps.join(', ')}`);
return activeIps;
}
}
+21 -6
View File
@@ -1,7 +1,7 @@
import dgram, { RemoteInfo } from 'dgram';
import { UdpSocketCommunicator } from "../socket_communicator/udp_socket_communicator";
import { OperationHandler } from "../operations_base/operation_handler";
import { GeneralOperations} from "../operations_custom/general_operations";
import { GeneralOperations } from "../operations_custom/general_operations";
export class UdpServer {
private readonly udpServer: dgram.Socket;
@@ -19,10 +19,20 @@ export class UdpServer {
this.operationHandler.loadPlugin(new GeneralOperations());
}
// Unified logging function
private log(message: string, level: 'log' | 'error' = 'log'): void {
const prefix = '[UdpServer]';
if (level === 'error') {
console.error(`${prefix} ${message}`);
} else {
console.log(`${prefix} ${message}`);
}
}
// Start the UDP server
public start(): void {
this.udpServer.on('message', this.handleUdpMessages.bind(this));
this.udpServer.on('error', this.handleError);
this.udpServer.on('error', this.handleError.bind(this));
this.udpServer.on('listening', this.handleListening.bind(this));
// Bind the server to the UDP port and host
@@ -34,7 +44,7 @@ export class UdpServer {
const ip = rinfo.address;
const port = rinfo.port;
//console.log(`Received message from ${ip}:${port}`);
this.log(`Received message from ${ip}:${port}`);
// Create a temporary communicator for the incoming message
const communicator = new UdpSocketCommunicator(this.udpServer, ip, port, this.operationHandler);
@@ -45,18 +55,23 @@ export class UdpServer {
const communicatorResult = communicator.getHandlerResult();
if (communicatorResult) {
// Send response back to the client using the temporary communicator
await communicator.sendMessage(communicatorResult.operationCode, communicatorResult.metaInfo);
try {
await communicator.sendMessage(communicatorResult.operationCode, communicatorResult.metaInfo);
this.log(`Sent response to ${ip}:${port}`);
} catch (error: any) {
this.log(`Error sending response to ${ip}:${port}: ${error.message}`, 'error');
}
}
}
// Handle UDP server errors
private handleError(err: Error): void {
console.error(`UDP server error:\n${err.stack}`);
this.log(`UDP server error:\n${err.stack}`, 'error');
}
// Handle when the UDP server starts listening
private handleListening(): void {
const address = this.udpServer.address();
console.log(`UDP server listening on ${address.address}:${address.port}`);
this.log(`UDP server listening on ${address.address}:${address.port}`);
}
}