network chunk v20
This commit is contained in:
@@ -14,6 +14,8 @@ export class BackupManager {
|
||||
private userConfig: JsonManager;
|
||||
private readonly clientPort: number;
|
||||
private isBusy: boolean = false;
|
||||
private intervalId: NodeJS.Timeout | null = null;
|
||||
private stopRequested: boolean = false;
|
||||
|
||||
constructor(userConfigPath: string, applicationInfoPath: string, memoryManagerPath: string, clientPort: number) {
|
||||
this.applicationInfo = new JsonManager(applicationInfoPath);
|
||||
@@ -23,8 +25,8 @@ export class BackupManager {
|
||||
}
|
||||
|
||||
async start(): Promise<void> {
|
||||
setInterval(async () => {
|
||||
if (!this.isBusy) {
|
||||
this.intervalId = setInterval(async () => {
|
||||
if (!this.isBusy || !this.stopRequested) {
|
||||
this.isBusy = true;
|
||||
this.log('Start successfully. Backup files to users.');
|
||||
await this.initialize();
|
||||
@@ -160,6 +162,22 @@ export class BackupManager {
|
||||
});
|
||||
}
|
||||
|
||||
async stop(): Promise<void> {
|
||||
this.stopRequested = true; // Signal that stop is requested
|
||||
|
||||
if (this.intervalId) {
|
||||
clearInterval(this.intervalId);
|
||||
this.intervalId = null;
|
||||
}
|
||||
|
||||
// Wait for any ongoing process to complete if busy
|
||||
while (this.isBusy) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
console.log("[BackupManager] Stopped successfully.");
|
||||
}
|
||||
|
||||
// Unified logging function
|
||||
private log(message: string, level: 'log' | 'error' | 'warn' = 'log'): void {
|
||||
const prefix = '[BackupManager]';
|
||||
|
||||
@@ -14,6 +14,8 @@ export class BackupRetrievalWorker {
|
||||
private encryptionKey: Buffer | null = null;
|
||||
private iv: Buffer | null = null;
|
||||
private tcpCommunicator: TcpCommunicator | null = null;
|
||||
private stopRequested: boolean = false;
|
||||
private isBusy: boolean = false;
|
||||
|
||||
constructor(userConfigPath: string, applicationInfoPath: string, clientPort: number, destinationPath: string) {
|
||||
this.userConfig = new JsonManager(userConfigPath);
|
||||
@@ -33,6 +35,8 @@ export class BackupRetrievalWorker {
|
||||
}
|
||||
|
||||
async start(): Promise<void> {
|
||||
if(!this.stopRequested) return;
|
||||
this.isBusy = true;
|
||||
try {
|
||||
const userInfo = await this.userConfig.readValue('user_info');
|
||||
if (!userInfo || !userInfo.name) {
|
||||
@@ -61,10 +65,15 @@ export class BackupRetrievalWorker {
|
||||
this.log(`Backup retrieved successfully from ${ip}`);
|
||||
}
|
||||
|
||||
process.send?.({ type: 'log', message: 'Backup retrieval completed successfully.' });
|
||||
process.send?.({ type: 'showAlert', message: 'Backup retrieval completed successfully.' });
|
||||
process.send?.({ type: 'changeContent', page: 'main_menu' });
|
||||
} catch (error: any) {
|
||||
this.log(`Error in BackupRetrievalWorker: ${error.message}`, 'error');
|
||||
process.send?.({ type: 'log', message: `A problem occurred: ${error.message}` });
|
||||
process.send?.({ type: 'showAlert', message: `A problem occurred: ${error.message}` });
|
||||
process.send?.({ type: 'changeContent', page: 'main_menu' });
|
||||
}
|
||||
finally {
|
||||
this.isBusy = false;
|
||||
}
|
||||
|
||||
if (global.gc) {
|
||||
@@ -172,6 +181,17 @@ export class BackupRetrievalWorker {
|
||||
}
|
||||
}
|
||||
|
||||
async stop(): Promise<void> {
|
||||
this.stopRequested = true; // Signal that stop is requested
|
||||
|
||||
// Wait for any ongoing process to complete if busy
|
||||
while (this.isBusy) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
console.log("[BackupManager] Stopped successfully.");
|
||||
}
|
||||
|
||||
private async waitForResponse(): Promise<ParsedMessage | null> {
|
||||
return new Promise((resolve) => {
|
||||
const idResponseCheck = setInterval(async () => {
|
||||
|
||||
@@ -14,6 +14,8 @@ export class DepartmentSharer {
|
||||
private readonly clientPort: number;
|
||||
private isBusy: boolean = false;
|
||||
private tcpCommunicator: TcpCommunicator | null = null;
|
||||
private stopRequested: boolean = false;
|
||||
private intervalId: NodeJS.Timeout | null = null;
|
||||
|
||||
constructor(
|
||||
userConfigPath: string,
|
||||
@@ -30,8 +32,8 @@ export class DepartmentSharer {
|
||||
|
||||
// Start sharing files with the department every minute
|
||||
async start(): Promise<void> {
|
||||
setInterval(async () => {
|
||||
if (!this.isBusy) {
|
||||
this.intervalId = setInterval(async () => {
|
||||
if (!this.isBusy || !this.stopRequested) {
|
||||
this.isBusy = true;
|
||||
this.log('Start successfully. Sharing files with the department.');
|
||||
await this.shareFilesWithDepartment();
|
||||
@@ -172,6 +174,22 @@ export class DepartmentSharer {
|
||||
}
|
||||
}
|
||||
|
||||
async stop(): Promise<void> {
|
||||
this.stopRequested = true; // Signal that stop is requested
|
||||
|
||||
if (this.intervalId) {
|
||||
clearInterval(this.intervalId);
|
||||
this.intervalId = null;
|
||||
}
|
||||
|
||||
// Wait for any ongoing process to complete if busy
|
||||
while (this.isBusy) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
console.log("[BackupManager] Stopped successfully.");
|
||||
}
|
||||
|
||||
private async waitForResponse(): Promise<ParsedMessage | null> {
|
||||
return new Promise((resolve) => {
|
||||
const idResponseCheck = setInterval(async () => {
|
||||
|
||||
@@ -17,6 +17,8 @@ export class FileSharer {
|
||||
private readonly clientPort: number;
|
||||
private isBusy: boolean;
|
||||
private tcpCommunicator: TcpCommunicator | null = null;
|
||||
private stopRequested: boolean = false;
|
||||
private intervalId: NodeJS.Timeout | null = null;
|
||||
|
||||
constructor(queueFilePath: string, clientPort: number) {
|
||||
this.queueManager = new QueueManager<FileItemTask>(queueFilePath, compareFnFileItemTask);
|
||||
@@ -26,8 +28,8 @@ export class FileSharer {
|
||||
|
||||
// Start processing the file queue
|
||||
async start(): Promise<void> {
|
||||
setInterval(async () => {
|
||||
if (!this.isBusy) { // Check if the queue is already being processed
|
||||
this.intervalId = setInterval(async () => {
|
||||
if (!this.isBusy || !this.stopRequested) { // Check if the queue is already being processed
|
||||
this.isBusy = true; // Set busy flag to true before starting
|
||||
this.log("Start successfully. Processing the queue.");
|
||||
await this.processQueue();
|
||||
@@ -104,6 +106,22 @@ export class FileSharer {
|
||||
return true;
|
||||
}
|
||||
|
||||
async stop(): Promise<void> {
|
||||
this.stopRequested = true; // Signal that stop is requested
|
||||
|
||||
if (this.intervalId) {
|
||||
clearInterval(this.intervalId);
|
||||
this.intervalId = null;
|
||||
}
|
||||
|
||||
// Wait for any ongoing process to complete if busy
|
||||
while (this.isBusy) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
console.log("[BackupManager] Stopped successfully.");
|
||||
}
|
||||
|
||||
private async waitForResponse(): Promise<ParsedMessage | null> {
|
||||
return new Promise((resolve) => {
|
||||
const idResponseCheck = setInterval(async () => {
|
||||
|
||||
@@ -54,7 +54,7 @@ export class NetworkScanner {
|
||||
try {
|
||||
this.log('UC Check running...', 'log', 'startUCCheck');
|
||||
const udpClient = new UdpClient(this.udpPort);
|
||||
const aliveClients = await udpClient.getAliveClients();
|
||||
const aliveClients = await udpClient.getTargetClients(operationCodes.ARE_YOU_UC);
|
||||
const storedIp = await this.applicationInfo.readValue('serverIp');
|
||||
const foundClient = aliveClients.length > 0;
|
||||
|
||||
@@ -95,7 +95,7 @@ export class NetworkScanner {
|
||||
this.log('IP Lookup running...', 'log', 'startUserIPLookup');
|
||||
const serverIp = await this.applicationInfo.readValue('serverIp');
|
||||
const udpClient = new UdpClient(this.udpPort);
|
||||
const activeIPs = await udpClient.getAliveClients();
|
||||
const activeIPs = await udpClient.getTargetClients(operationCodes.ARE_YOU_HUMAN);
|
||||
const filteredIPs = activeIPs.filter(ip => ip !== serverIp);
|
||||
|
||||
// Save the filtered IPs to 'users_ip'
|
||||
|
||||
@@ -11,6 +11,7 @@ export class UsersInfoFetcher {
|
||||
private readonly clientPort: number;
|
||||
private memoryId: string;
|
||||
private readonly activeUsersKey: string;
|
||||
private intervalId: NodeJS.Timeout | null = null;
|
||||
|
||||
constructor(applicationInfoPath: string, memoryManagerPath: string, clientPort: number) {
|
||||
this.applicationInfo = new JsonManager(applicationInfoPath);
|
||||
@@ -23,13 +24,13 @@ export class UsersInfoFetcher {
|
||||
|
||||
// Method to start checking user info periodically (every minute)
|
||||
async start(): Promise<void> {
|
||||
setInterval(async () => {
|
||||
this.intervalId = setInterval(async () => {
|
||||
await this.initialize(); // Re-run every minute
|
||||
|
||||
if (global.gc) {
|
||||
global.gc();
|
||||
}
|
||||
}, 5000); // 1 minute interval
|
||||
}, 5000); // 5-second interval for testing
|
||||
}
|
||||
|
||||
// Initialize and fetch user IPs and process users info
|
||||
@@ -101,6 +102,14 @@ export class UsersInfoFetcher {
|
||||
await this.memoryManager.updateMetaInformation(this.memoryId, userInfo); // Update active users in memory
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
if (this.intervalId) {
|
||||
clearInterval(this.intervalId);
|
||||
this.intervalId = null;
|
||||
console.log("[UsersInfoFetcher] Stopped successfully.");
|
||||
}
|
||||
}
|
||||
|
||||
// Unified logging function
|
||||
private log(message: string, level: 'log' | 'error' = 'log'): void {
|
||||
const prefix = '[UsersInfoFetcher]';
|
||||
|
||||
@@ -5,7 +5,8 @@ import { WindowManager } from "./window_manager";
|
||||
export class WorkerManager {
|
||||
private readonly pathToWorkerDir: string;
|
||||
private windowManager: WindowManager;
|
||||
private workers: ChildProcess[]; // Array to store running child processes
|
||||
private workers: ChildProcess[];
|
||||
private cleanupInProgress: boolean = false;
|
||||
|
||||
constructor(pathToWorkerDir: string, windowManager: WindowManager) {
|
||||
this.pathToWorkerDir = pathToWorkerDir;
|
||||
@@ -87,17 +88,24 @@ export class WorkerManager {
|
||||
reject(err);
|
||||
});
|
||||
|
||||
worker.on('exit', (code) => {
|
||||
console.log(`${scriptName} exited with code ${code}`);
|
||||
worker.on('exit', (code, signal) => {
|
||||
this.removeWorker(worker);
|
||||
if (code === 0) resolve();
|
||||
else reject(new Error(`${scriptName} exited with code ${code}`));
|
||||
if (code === 0) {
|
||||
console.log(`${scriptName} exited successfully`);
|
||||
resolve();
|
||||
} else if (signal) {
|
||||
console.log(`${scriptName} was killed with signal: ${signal}`);
|
||||
} else {
|
||||
console.error(`${scriptName} exited with code: ${code}`);;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Close all running workers
|
||||
closeAllWorkers(): void {
|
||||
if (this.cleanupInProgress) return; // Prevent duplicate cleanup
|
||||
this.cleanupInProgress = true;
|
||||
|
||||
console.log('Terminating all running workers...');
|
||||
this.workers.forEach(worker => worker.kill());
|
||||
this.workers = [];
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export let operationCodes = {
|
||||
// General Operations
|
||||
HEARTBEAT: 'HEARTBEAT',
|
||||
ARE_YOU_HUMAN: 'ARE_YOU_HUMAN',
|
||||
ARE_YOU_UC: 'ARE_YOU_UC',
|
||||
ALIVE: 'ALIVE',
|
||||
SET_PUBLIC_KEY: 'SET_PUBLIC_KEY',
|
||||
SET_AES_KEY: 'SET_AES_KEY',
|
||||
|
||||
@@ -7,14 +7,14 @@ export class GeneralOperations implements OperationPlugin {
|
||||
public static readonly operationCodes = {
|
||||
OK: 'OK',
|
||||
ERR: 'ERR',
|
||||
HEARTBEAT: 'HEARTBEAT',
|
||||
ARE_YOU_HUMAN: 'ARE_YOU_HUMAN',
|
||||
ALIVE: 'ALIVE',
|
||||
SET_PUBLIC_KEY: 'SET_PUBLIC_KEY',
|
||||
SET_AES_KEY: 'SET_AES_KEY',
|
||||
};
|
||||
|
||||
// Handle heartbeat operation asynchronously
|
||||
public static async handleHeartbeat(): Promise<ParsedMessage> {
|
||||
public static async handleAreYouHuman(): Promise<ParsedMessage> {
|
||||
const networkInterfaces = os.networkInterfaces();
|
||||
let ipAddress = 'Unknown';
|
||||
|
||||
@@ -79,7 +79,7 @@ export class GeneralOperations implements OperationPlugin {
|
||||
|
||||
// Register general operations with the OperationHandler
|
||||
public register(operationHandler: OperationHandler): void {
|
||||
operationHandler.registerHandler(GeneralOperations.operationCodes.HEARTBEAT, GeneralOperations.handleHeartbeat);
|
||||
operationHandler.registerHandler(GeneralOperations.operationCodes.ARE_YOU_HUMAN, GeneralOperations.handleAreYouHuman);
|
||||
operationHandler.registerHandler(GeneralOperations.operationCodes.SET_PUBLIC_KEY, GeneralOperations.handlePublicKey);
|
||||
operationHandler.registerHandler(GeneralOperations.operationCodes.SET_AES_KEY, GeneralOperations.handleAESKey);
|
||||
operationHandler.registerHandler(GeneralOperations.operationCodes.OK, GeneralOperations.handleOk);
|
||||
|
||||
@@ -29,7 +29,7 @@ export class UdpClient {
|
||||
}
|
||||
|
||||
// Send heartbeat and get clients that respond with ALIVE, excluding the host machine's IP addresses
|
||||
async getAliveClients(): Promise<string[]> {
|
||||
async getTargetClients(heartbeatCode: string): Promise<string[]> {
|
||||
const subnet = this.getSubnet();
|
||||
const ipRange = this.getIPRange(subnet);
|
||||
|
||||
@@ -45,7 +45,7 @@ export class UdpClient {
|
||||
const aliveClients: string[] = [];
|
||||
for (const ip of activeIps) {
|
||||
if (!localIPs.includes(ip)) {
|
||||
const result = await this.sendHeartbeat(ip);
|
||||
const result = await this.sendHeartbeat(ip, heartbeatCode);
|
||||
if (result.found) {
|
||||
aliveClients.push(ip);
|
||||
}
|
||||
@@ -73,9 +73,8 @@ export class UdpClient {
|
||||
}
|
||||
|
||||
// Send heartbeat to an IP
|
||||
private async sendHeartbeat(ip: string): Promise<{ found: boolean }> {
|
||||
private async sendHeartbeat(ip: string, heartbeatCode: string): Promise<{ found: boolean }> {
|
||||
return new Promise((resolve) => {
|
||||
const heartbeatCode = operationCodes.HEARTBEAT;
|
||||
const heartbeatMessage = MessageHandler.formatMessage(heartbeatCode);
|
||||
|
||||
this.log(`Sending heartbeat to ${ip}`);
|
||||
|
||||
@@ -25,4 +25,26 @@ const backupRetrievalWorker = new BackupRetrievalWorker(
|
||||
);
|
||||
|
||||
// Start the backup retrieval process
|
||||
backupRetrievalWorker.start();
|
||||
backupRetrievalWorker.start().then(() => {
|
||||
console.log('Backup retrieval process completed successfully.');
|
||||
});
|
||||
|
||||
process.on('SIGTERM', async () => {
|
||||
console.log('Received SIGTERM. Cleaning up...');
|
||||
await cleanupAndExit();
|
||||
});
|
||||
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('Received SIGINT. Cleaning up...');
|
||||
await cleanupAndExit();
|
||||
});
|
||||
|
||||
async function cleanupAndExit() {
|
||||
// Perform any cleanup, such as closing connections, saving data, etc.
|
||||
// Example: if you have a server instance running, you may want to close it:
|
||||
// await server.close();
|
||||
|
||||
console.log('Cleanup complete. Exiting.');
|
||||
process.exit(0); // Exit with code 0 to indicate a clean exit
|
||||
}
|
||||
|
||||
|
||||
@@ -23,3 +23,22 @@ departmentShareManager.start();
|
||||
|
||||
const shareFileManager = new DirectoryWatcher(memoryManagerPath, applicationInfoPath, 'shareDirectory');
|
||||
shareFileManager.start();
|
||||
|
||||
process.on('SIGTERM', async () => {
|
||||
console.log('Received SIGTERM. Cleaning up...');
|
||||
await cleanupAndExit();
|
||||
});
|
||||
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('Received SIGINT. Cleaning up...');
|
||||
await cleanupAndExit();
|
||||
});
|
||||
|
||||
async function cleanupAndExit() {
|
||||
backupDirectoryManager.closeWatcher();
|
||||
departmentShareManager.closeWatcher();
|
||||
shareFileManager.closeWatcher();
|
||||
|
||||
console.log('Cleanup complete. Exiting.');
|
||||
process.exit(0); // Exit with code 0 to indicate a clean exit
|
||||
}
|
||||
|
||||
@@ -20,3 +20,20 @@ const networkScanner = new NetworkScanner(
|
||||
errorPage,
|
||||
databaseResetPage
|
||||
);
|
||||
|
||||
process.on('SIGTERM', async () => {
|
||||
console.log('Received SIGTERM. Cleaning up...');
|
||||
await cleanupAndExit();
|
||||
});
|
||||
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('Received SIGINT. Cleaning up...');
|
||||
await cleanupAndExit();
|
||||
});
|
||||
|
||||
async function cleanupAndExit() {
|
||||
networkScanner.stopAllIntervals();
|
||||
|
||||
console.log('Cleanup complete. Exiting.');
|
||||
process.exit(0); // Exit with code 0 to indicate a clean exit
|
||||
}
|
||||
|
||||
@@ -21,3 +21,23 @@ fileSharer.start();
|
||||
|
||||
const departmentSharer = new DepartmentSharer(usersConfigPath, applicationInfoPath, memoryManagerPath, tcpPort);
|
||||
departmentSharer.start();
|
||||
|
||||
process.on('SIGTERM', async () => {
|
||||
console.log('Received SIGTERM. Cleaning up...');
|
||||
await cleanupAndExit();
|
||||
});
|
||||
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('Received SIGINT. Cleaning up...');
|
||||
await cleanupAndExit();
|
||||
});
|
||||
|
||||
async function cleanupAndExit() {
|
||||
usersInfoFetcher.stop();
|
||||
await backupManager.stop();
|
||||
await fileSharer.stop();
|
||||
await departmentSharer.stop();
|
||||
|
||||
console.log('Cleanup complete. Exiting.');
|
||||
process.exit(0); // Exit with code 0 to indicate a clean exit
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { UdpServer } from "../network/udp/udp_server";
|
||||
import { TcpServer } from "../network/tcp/tcp_server";
|
||||
|
||||
let udpServer: UdpServer | null = null;
|
||||
let tcpServer: TcpServer | null = null;
|
||||
let udpServer: UdpServer | null
|
||||
let tcpServer: TcpServer | null
|
||||
|
||||
// Retrieve data from environment variables
|
||||
const USER_UDP_PORT = parseInt(process.env.USER_UDP_PORT || '0', 10);
|
||||
@@ -15,3 +15,22 @@ udpServer.start();
|
||||
|
||||
tcpServer = new TcpServer(HOST, USER_TCP_PORT);
|
||||
tcpServer.start();
|
||||
|
||||
process.on('SIGTERM', async () => {
|
||||
console.log('Received SIGTERM. Cleaning up...');
|
||||
await cleanupAndExit();
|
||||
});
|
||||
|
||||
process.on('SIGINT', async () => {
|
||||
console.log('Received SIGINT. Cleaning up...');
|
||||
await cleanupAndExit();
|
||||
});
|
||||
|
||||
async function cleanupAndExit() {
|
||||
// Perform any cleanup, such as closing connections, saving data, etc.
|
||||
// Example: if you have a server instance running, you may want to close it:
|
||||
// await server.close();
|
||||
|
||||
console.log('Cleanup complete. Exiting.');
|
||||
process.exit(0); // Exit with code 0 to indicate a clean exit
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user