From b0754d00c67296733c48fbef673180884a384c4b Mon Sep 17 00:00:00 2001 From: andrei-mihnea-cerbu Date: Tue, 4 Feb 2025 20:43:05 +0200 Subject: [PATCH] simplified gathering information from clients --- User/src/helpers/network_scanner.ts | 13 ++- User/src/helpers/users_info_fetcher.ts | 92 ------------------- User/src/ipc-handlers/database_handler.ts | 6 +- User/src/main/preload.ts | 6 +- .../operations_custom/general_operations.ts | 20 +++- .../user_to_user_operations.ts | 28 +----- User/src/network/udp/udp_client.ts | 10 +- .../workers/resource_coordinator_worker.ts | 5 - 8 files changed, 43 insertions(+), 137 deletions(-) delete mode 100644 User/src/helpers/users_info_fetcher.ts diff --git a/User/src/helpers/network_scanner.ts b/User/src/helpers/network_scanner.ts index aa6dff9..a8adcb4 100644 --- a/User/src/helpers/network_scanner.ts +++ b/User/src/helpers/network_scanner.ts @@ -110,16 +110,15 @@ export class NetworkScanner { const data = await this.db.read() const serverIp = data.network.serverIp const udpClient = new UdpClient(this.udpPort) - const activeIPs = await udpClient.getTargetClients(operationCodes.ARE_YOU_HUMAN) - const filteredIPs = activeIPs.filter((ip) => ip !== serverIp) + const activeClients = await udpClient.getTargetClients(operationCodes.ARE_YOU_HUMAN) // Save the filtered IPs to 'users_ip' await this.db.update((data) => { - data.network.usersInLan = filteredIPs.map((ip) => ({ - id: '', - ip, - name: '', - departmentId: '', + data.network.usersInLan = activeClients.map((client) => ({ + id: client.id, + ip: client.ip, + name: client.name, + departmentId: client.departmentId, })) return data }) diff --git a/User/src/helpers/users_info_fetcher.ts b/User/src/helpers/users_info_fetcher.ts deleted file mode 100644 index a43d0a9..0000000 --- a/User/src/helpers/users_info_fetcher.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { Database } from '../database/database' -import { NetworkUserScheme } from '../database/schemes/network_scheme' -import { TcpCommunicator } from './tcp_communicator' -import { operationCodes } from '../network/operation_codes' -import { ParsedMessage } from '../network/message_handler' - -export class UsersInfoFetcher { - private db: Database - private tcpCommunicator: TcpCommunicator | null = null - private readonly clientPort: number - private intervalId: NodeJS.Timeout | null = null - - constructor(pathToDatabaseFile: string, clientPort: number) { - this.db = new Database(pathToDatabaseFile) - this.clientPort = clientPort - this.tcpCommunicator = null - } - - // Start fetching user info periodically - async start(): Promise { - this.intervalId = setInterval(async () => { - const data = await this.db.read() - const usersIps = data.network.usersInLan.map((user: NetworkUserScheme) => user.ip) - - for (const ip of usersIps) { - this.tcpCommunicator = new TcpCommunicator(ip, this.clientPort) - if (!(await this.tcpCommunicator.connect())) { - this.log(`Failed to open connection for IP: ${ip}`, 'error') - continue - } - - if (!(await this.tcpCommunicator?.sendMessage(operationCodes.GET_USER_INFORMATION))) { - await this.tcpCommunicator.disconnect() - continue - } - - // Wait for the response - const response = await this.waitForResponse() - - if (response && response.metaInfo) { - await this.db.update((data) => { - const userIndex = data.network.usersInLan.findIndex((user) => user.ip === ip) - - if (userIndex !== -1) { - // @ts-ignore - data.network.usersInLan[userIndex].id = response.metaInfo.id - // @ts-ignore - data.network.usersInLan[userIndex].name = response.metaInfo.name - // @ts-ignore - data.network.usersInLan[userIndex].departmentId = response.metaInfo.departmentId - } else { - this.log(`User with IP ${ip} not found in the database.`, 'error') - } - - return data - }) - } - - await this.tcpCommunicator.disconnect() - } - - if (global.gc) { - global.gc() - } - }, 5000) // 5-second interval for testing - } - - private async waitForResponse(): Promise { - return new Promise((resolve) => { - const idResponseCheck = setInterval(async () => { - if (!this.tcpCommunicator) return null - if (this.tcpCommunicator.hasResponseArrived()) { - clearInterval(idResponseCheck) - resolve(this.tcpCommunicator.getLastResult()) - } - }, 100) // Check every 100ms - }) - } - - stop(): void { - if (this.intervalId) { - clearInterval(this.intervalId) - this.intervalId = null - this.log('Stopped successfully.') - } - } - - private log(message: string, level: 'log' | 'error' = 'log'): void { - const prefix = '[UsersInfoFetcher]' - level === 'error' ? console.error(`${prefix} ${message}`) : console.log(`${prefix} ${message}`) - } -} diff --git a/User/src/ipc-handlers/database_handler.ts b/User/src/ipc-handlers/database_handler.ts index 375db28..93f44e7 100644 --- a/User/src/ipc-handlers/database_handler.ts +++ b/User/src/ipc-handlers/database_handler.ts @@ -2,7 +2,11 @@ import { Database } from '../database/database' import { DatabaseScheme } from '../database/schemes/database_scheme' import path from 'path' import { EncryptionKeyScheme, UserInfoScheme } from '../database/schemes/app_config_scheme' -import {DirectoryInfo, DirectorySchemes, FileItemTask} from '../database/schemes/local_resources_scheme' +import { + DirectoryInfo, + DirectorySchemes, + FileItemTask, +} from '../database/schemes/local_resources_scheme' const pathToDatabaseFile = path.join(__dirname, '..', 'database.json') diff --git a/User/src/main/preload.ts b/User/src/main/preload.ts index bc41361..b26015a 100644 --- a/User/src/main/preload.ts +++ b/User/src/main/preload.ts @@ -4,7 +4,11 @@ import { EncryptionKeyScheme, UserInfoScheme } from '../database/schemes/app_con import { ipcUCHandler } from '../ipc-handlers/uc_handler' import { ParsedMessage } from '../network/message_handler' import { NetworkUserScheme } from '../database/schemes/network_scheme' -import {DirectoryInfo, DirectorySchemes, FileItemTask} from '../database/schemes/local_resources_scheme' +import { + DirectoryInfo, + DirectorySchemes, + FileItemTask, +} from '../database/schemes/local_resources_scheme' contextBridge.exposeInMainWorld('databaseAPI', { getAppType: (): Promise => ipcDatabaseHandler.getAppType(), diff --git a/User/src/network/operations_custom/general_operations.ts b/User/src/network/operations_custom/general_operations.ts index 6f9fd53..e72903e 100644 --- a/User/src/network/operations_custom/general_operations.ts +++ b/User/src/network/operations_custom/general_operations.ts @@ -2,6 +2,10 @@ import { ParsedMessage } from '../message_handler' import { OperationHandler } from '../operations_base/operation_handler' import os from 'node:os' import { OperationPlugin } from '../operations_base/operation_plugin' +import { Database } from '../../database/database' +import path from 'path' + +const pathToDatabaseFile = path.join(__dirname, '..', '..', 'database.json') export class GeneralOperations implements OperationPlugin { public static readonly operationCodes = { @@ -28,9 +32,23 @@ export class GeneralOperations implements OperationPlugin { if (ipAddress !== 'Unknown') break } + const database = new Database(pathToDatabaseFile) + const data = await database.read() + let response = { + ip: ipAddress, + name: '', + departmentId: '', + id: '', + } + if (data.app_config.logged_in) { + response.name = data.app_config.user_info.name + response.departmentId = data.app_config.user_info.departmentId + response.id = data.app_config.user_info.id + } + return { operationCode: GeneralOperations.operationCodes.ALIVE, - metaInfo: { ipAddress }, + metaInfo: response, } } diff --git a/User/src/network/operations_custom/user_to_user_operations.ts b/User/src/network/operations_custom/user_to_user_operations.ts index 0d8ab28..4f0b43f 100644 --- a/User/src/network/operations_custom/user_to_user_operations.ts +++ b/User/src/network/operations_custom/user_to_user_operations.ts @@ -5,14 +5,13 @@ import path from 'path' import fs from 'fs/promises' import checkDiskSpace from 'check-disk-space' import { OperationPlugin } from '../operations_base/operation_plugin' -import {Database} from "../../database/database"; +import { Database } from '../../database/database' -const pathToDatabaseFile = path.join(__dirname, '..', '..', 'database.json') +const pathToDatabaseFile = path.join(__dirname, '..', '..', 'database.json') export class UserToUserOperations implements OperationPlugin { public static readonly operationCodes = { SEND_ANNOUNCEMENT: 'SEND_ANNOUNCEMENT', - GET_USER_INFORMATION: 'GET_USER_INFORMATION', BACKUP_FILE: 'BACKUP_FILE', CLEAR_BACKUP: 'CLEAR_BACKUP', SHARE_FILE: 'SHARE_FILE', @@ -51,7 +50,7 @@ export class UserToUserOperations implements OperationPlugin { const database = new Database(pathToDatabaseFile) try { await database.update((data: any) => { - if(!parsedMessage.metaInfo) return data; + if (!parsedMessage.metaInfo) return data data.app_config.announcement = parsedMessage.metaInfo.message return data @@ -63,23 +62,6 @@ export class UserToUserOperations implements OperationPlugin { } } - public static async handleGetUserInformation( - parsedMessage: ParsedMessage, - ): Promise { - const database = new Database(pathToDatabaseFile) - try { - const data = await database.read() - const userInfo = data.app_config.user_info - return { operationCode: operationCodes.OK, metaInfo: userInfo } - } catch (error: any) { - console.error(`Error fetching user info: ${error.message}`) - return { - operationCode: operationCodes.ERR, - metaInfo: { message: 'Error fetching user info' }, - } - } - } - public static async handleBackupFile(parsedMessage: ParsedMessage): Promise { if ( !parsedMessage.metaInfo?.userName || @@ -388,10 +370,6 @@ export class UserToUserOperations implements OperationPlugin { UserToUserOperations.operationCodes.SEND_ANNOUNCEMENT, UserToUserOperations.handleSendAnnouncement, ) - operationHandler.registerHandler( - UserToUserOperations.operationCodes.GET_USER_INFORMATION, - UserToUserOperations.handleGetUserInformation, - ) operationHandler.registerHandler( UserToUserOperations.operationCodes.BACKUP_FILE, UserToUserOperations.handleBackupFile, diff --git a/User/src/network/udp/udp_client.ts b/User/src/network/udp/udp_client.ts index 11002b4..bee94d4 100644 --- a/User/src/network/udp/udp_client.ts +++ b/User/src/network/udp/udp_client.ts @@ -29,7 +29,7 @@ export class UdpClient { } // Send heartbeat and get clients that respond with ALIVE, excluding the host machine's IP addresses - async getTargetClients(heartbeatCode: string): Promise { + async getTargetClients(heartbeatCode: string): Promise { const subnet = this.getSubnet() const ipRange = this.getIPRange(subnet) @@ -42,12 +42,12 @@ export class UdpClient { 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[] = [] + const aliveClients: any[] = [] for (const ip of activeIps) { if (!localIPs.includes(ip)) { const result = await this.sendHeartbeat(ip, heartbeatCode) if (result.found) { - aliveClients.push(ip) + aliveClients.push(result.data ? result.data : ip) } } } @@ -73,7 +73,7 @@ export class UdpClient { } // Send heartbeat to an IP - private async sendHeartbeat(ip: string, heartbeatCode: string): Promise<{ found: boolean }> { + private async sendHeartbeat(ip: string, heartbeatCode: string): Promise<{ found: boolean, data?: any }> { return new Promise((resolve) => { const heartbeatMessage = MessageHandler.formatMessage(heartbeatCode) @@ -94,7 +94,7 @@ export class UdpClient { const parsedMessage = MessageHandler.parseMessage(msg.toString()) if (parsedMessage?.operationCode === operationCodes.ALIVE) { this.log(`Received ALIVE response from ${ip}`) - resolve({ found: true }) + resolve({ found: true, data: parsedMessage.metaInfo }) } else { this.log(`Unexpected response from ${ip}`) resolve({ found: false }) diff --git a/User/src/workers/resource_coordinator_worker.ts b/User/src/workers/resource_coordinator_worker.ts index 348bddc..3112859 100644 --- a/User/src/workers/resource_coordinator_worker.ts +++ b/User/src/workers/resource_coordinator_worker.ts @@ -1,4 +1,3 @@ -import { UsersInfoFetcher } from '../helpers/users_info_fetcher' import { BackupManager } from '../helpers/backup_manager' import { FileSharer } from '../helpers/file_sharer' import { DepartmentSharer } from '../helpers/department_sharer' @@ -7,9 +6,6 @@ import { DepartmentSharer } from '../helpers/department_sharer' const pathToDatabaseFile = process.env.DATABASE_FILE_PATH || '' const tcpPort = parseInt(process.env.TCP_PORT || '0', 10) -const usersInfoFetcher = new UsersInfoFetcher(pathToDatabaseFile, tcpPort) -usersInfoFetcher.start() - const backupManager = new BackupManager(pathToDatabaseFile, tcpPort) backupManager.start() @@ -30,7 +26,6 @@ process.on('SIGINT', async () => { }) async function cleanupAndExit() { - usersInfoFetcher.stop() await backupManager.stop() await fileSharer.stop() await departmentSharer.stop()