import {QueueManager} from './queue_manager'; import {TcpCommunicator} from "./tcp_communicator"; // Updated to use TcpCommunicator import {operationCodes} from '../network/operation_codes'; import fs from "fs"; import path from "path"; import {compareFnFileItemTask, FileItemTask} from "../interfaces/file_item_task"; import {ParsedMessage} from "../network/message_handler"; interface FileSendTask { ip: string; path: string; userName: string; } export class FileSharer { private queueManager: QueueManager; private readonly clientPort: number; private isBusy: boolean; private tcpCommunicator: TcpCommunicator | null = null; constructor(queueFilePath: string, clientPort: number) { this.queueManager = new QueueManager(queueFilePath, compareFnFileItemTask); this.clientPort = clientPort; this.isBusy = false; // Initialize the busy flag } // Start processing the file queue async start(): Promise { setInterval(async () => { if (!this.isBusy) { // Check if the queue is already being processed await this.processQueue(); // Process the queue at regular intervals } }, 10000); // 10 seconds interval } // Method to process the queue private async processQueue(): Promise { if (this.isBusy) { console.log("Queue is already being processed. Skipping this interval."); return; } this.isBusy = true; // Set busy flag to true before starting while (!this.queueManager.isEmpty()) { const task = this.queueManager.peek(); if (task) { console.log(task); const success = await this.sendFile(task); if (!success) { console.error(`Failed to send file: ${task.path} to IP: ${task.ip}. Re-adding to queue.`); this.queueManager.dequeue(); this.queueManager.enqueue(task); // Re-add to queue if failed } else { console.log(`File sent successfully: ${task.path} to IP: ${task.ip}.`); this.queueManager.dequeue(); } } } this.isBusy = false; // Reset busy flag after the queue is processed } // Method to send the file to a specific IP using TcpCommunicator private async sendFile(task: FileSendTask): Promise { const {ip, path: filePath, userName} = task; // Ensure the file exists before attempting to send if (!fs.existsSync(filePath)) { console.error(`File not found: ${filePath}`); return false; } // Read the file contents const fileContent = fs.readFileSync(filePath); // Extract the file name from the file path using path.basename const fileName = path.basename(filePath); const metaInfo = { userName, // Sender's username relativeFilePath: fileName, // Use the file name instead of the full path }; this.tcpCommunicator = new TcpCommunicator(ip, this.clientPort); if (!await this.tcpCommunicator.connect()) { console.error(`Failed to connect to IP: ${ip}`); return false; } console.log(`Sending file: ${filePath} to IP: ${ip}`); if (!await this.tcpCommunicator.sendMessage(operationCodes.SHARE_FILE, metaInfo, fileContent)) return false; const response = await this.waitForResponse(); if (!response || response.operationCode !== operationCodes.OK) { console.error(`Failed to send file: ${filePath} to IP: ${ip}`); return false; } await this.tcpCommunicator.disconnect(); return true; } 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()); // Resolve the response or null if not available } }, 100); // Check every 100 milliseconds if the response has arrived }); } }