simplified gathering information from clients
This commit is contained in:
@@ -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
|
||||
})
|
||||
|
||||
@@ -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<void> {
|
||||
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<ParsedMessage | null> {
|
||||
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}`)
|
||||
}
|
||||
}
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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<string> => ipcDatabaseHandler.getAppType(),
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
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,
|
||||
|
||||
@@ -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<string[]> {
|
||||
async getTargetClients(heartbeatCode: string): Promise<any[]> {
|
||||
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 })
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user