program finalizat

This commit is contained in:
andrei-mihnea-cerbu
2024-10-29 15:07:26 +02:00
parent ab1eaec413
commit 979539d3db
138 changed files with 14602 additions and 5068 deletions
+46 -80
View File
@@ -1,9 +1,10 @@
import { QueueManager } from './queue_manager'; // Assume the QueueManager is in this path
import { TcpClient } from '../network/tcp/tcp_client'; // Import your TcpClient class
import { operationCodes } from '../network/operation_codes';
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;
@@ -14,45 +15,56 @@ interface FileSendTask {
export class FileSharer {
private queueManager: QueueManager<FileSendTask>;
private readonly clientPort: number;
private isBusy: boolean;
private tcpCommunicator: TcpCommunicator | null = null;
constructor(queueFilePath: string, clientPort: number) {
this.queueManager = new QueueManager<FileItemTask>(queueFilePath, compareFnFileItemTask);
this.clientPort = clientPort;
this.isBusy = false; // Initialize the busy flag
}
// Start processing the file queue
async start(): Promise<void> {
setInterval(async () => {
await this.processQueue(); // Process the queue at regular intervals
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<void> {
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{
} 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 the TcpClient
// Method to send the file to a specific IP using TcpCommunicator
private async sendFile(task: FileSendTask): Promise<boolean> {
const { ip, path: filePath, userName } = task;
const {ip, path: filePath, userName} = task;
// Ensure the file exists before attempting to send
if (!fs.existsSync(filePath)) {
@@ -63,7 +75,7 @@ export class FileSharer {
// Read the file contents
const fileContent = fs.readFileSync(filePath);
// Extract the file name from the file path using path.basename (handles both Windows and Unix)
// Extract the file name from the file path using path.basename
const fileName = path.basename(filePath);
const metaInfo = {
@@ -71,82 +83,36 @@ export class FileSharer {
relativeFilePath: fileName, // Use the file name instead of the full path
};
const tcpClient = new TcpClient(this.clientPort);
tcpClient.openSocket(ip);
this.tcpCommunicator = new TcpCommunicator(ip, this.clientPort);
// Wait for the AES key and then send the file
try {
const sendSuccess = await this.waitForAesKeyAndSendFile(tcpClient, operationCodes.SHARE_FILE, metaInfo, fileContent, task);
tcpClient.closeSocket();
return sendSuccess;
} catch (error) {
console.error(`Error sending file: ${filePath} to IP: ${ip}. Error: ${error}`);
tcpClient.closeSocket();
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;
}
// Wait for AES key to be set and send the file, handling the response
private async waitForAesKeyAndSendFile(tcpClient: TcpClient, operationCode: string, metaInfo: { [key: string]: any }, fileContent: Buffer, task: FileSendTask, checkInterval: number = 500, timeout: number = 10000): Promise<boolean> {
const startTime = Date.now();
return new Promise((resolve, reject) => {
const intervalId = setInterval(async () => {
const elapsedTime = Date.now() - startTime;
// Check if AES key is set, if timeout occurs, reject
if (!tcpClient.isAesKeySet()) {
if (elapsedTime > timeout) {
clearInterval(intervalId);
console.error('Timeout waiting for AES key.');
reject(new Error('Timeout waiting for AES key.'));
}
return; // Continue waiting for AES key
}
// AES key is set, send the message
clearInterval(intervalId);
try {
const success = await tcpClient.sendMessage(operationCode, metaInfo, fileContent);
if (!success) {
reject(new Error('Failed to send the file content.'));
return;
}
// Wait for a response after sending the message
const responseReceived = await this.waitForMessageResponse(tcpClient, timeout);
if (!responseReceived) {
reject(new Error('Timeout waiting for the message response.'));
return;
}
resolve(true); // Everything went fine
} catch (error) {
reject(error);
}
}, checkInterval); // Check for AES key every `checkInterval`
});
}
// Method to wait for the response from the TCP client
private waitForMessageResponse(tcpClient: TcpClient, timeout: number = 10000): Promise<boolean> {
private async waitForResponse(): Promise<ParsedMessage | null> {
return new Promise((resolve) => {
const startTime = Date.now();
const intervalId = setInterval(() => {
const response = tcpClient.getLastResult();
const elapsedTime = Date.now() - startTime;
if (response?.operationCode === operationCodes.OK) {
clearInterval(intervalId);
resolve(true); // Message successfully received
} else if (elapsedTime > timeout) {
clearInterval(intervalId);
resolve(false); // No response after timeout
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 100ms
}, 100); // Check every 100 milliseconds if the response has arrived
});
}
}