BACKEND DONE FOR ALL APPS
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
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 fs from "fs";
|
||||
import path from "path";
|
||||
import {compareFnFileItemTask, FileItemTask} from "../interfaces/file_item_task";
|
||||
|
||||
interface FileSendTask {
|
||||
ip: string;
|
||||
path: string;
|
||||
userName: string;
|
||||
}
|
||||
|
||||
export class FileSharer {
|
||||
private queueManager: QueueManager<FileSendTask>;
|
||||
private readonly clientPort: number;
|
||||
|
||||
constructor(queueFilePath: string, clientPort: number) {
|
||||
|
||||
|
||||
this.queueManager = new QueueManager<FileItemTask>(queueFilePath, compareFnFileItemTask);
|
||||
this.clientPort = clientPort;
|
||||
}
|
||||
|
||||
// Start processing the file queue
|
||||
async start(): Promise<void> {
|
||||
setInterval(async () => {
|
||||
await this.processQueue(); // Process the queue at regular intervals
|
||||
}, 10000); // 10 seconds interval
|
||||
}
|
||||
|
||||
// Method to process the queue
|
||||
private async processQueue(): Promise<void> {
|
||||
while (!this.queueManager.isEmpty()) {
|
||||
const task = this.queueManager.peek();
|
||||
|
||||
if (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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method to send the file to a specific IP using the TcpClient
|
||||
private async sendFile(task: FileSendTask): Promise<boolean> {
|
||||
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 (handles both Windows and Unix)
|
||||
const fileName = path.basename(filePath);
|
||||
|
||||
const metaInfo = {
|
||||
userName, // Sender's username
|
||||
relativeFilePath: fileName, // Use the file name instead of the full path
|
||||
};
|
||||
|
||||
const tcpClient = new TcpClient(this.clientPort);
|
||||
tcpClient.openSocket(ip);
|
||||
|
||||
// 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();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 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> {
|
||||
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
|
||||
}
|
||||
}, 100); // Check every 100ms
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user