khamba
Version:
A cli tool for sharing files through local network.
87 lines (86 loc) • 3.34 kB
JavaScript
import crypto from 'crypto';
import path from 'path';
import fs from 'fs';
import { updateTransferFileErrorMsg, updateTransferFileState, } from '../stores/receiverfileHandlerStore.js';
import { RECEIVE_PATH } from '../functions/variables.js';
import { log, logError } from '../functions/log.js';
import { fetchUpdateSenderTransferState } from '../functions/fetch.js';
export const hashFile = async (filePath) => {
return new Promise((resolve, reject) => {
const hash = crypto.createHash('sha256');
const stream = fs.createReadStream(filePath);
stream.on('data', chunk => {
hash.update(chunk);
});
stream.on('end', () => {
resolve(hash.digest('hex'));
});
stream.on('error', error => {
logError(error);
reject(error);
});
});
};
export const hashFolder = async (folderPath) => {
const hash = crypto.createHash('sha256');
try {
const files = fs.readdirSync(folderPath);
for (const file of files) {
const filePath = path.join(folderPath, file);
const stats = fs.statSync(filePath);
if (stats.isDirectory()) {
const subFolderHash = await hashFolder(filePath);
hash.update(subFolderHash);
}
else {
const fileHash = await hashFile(filePath);
hash.update(fileHash);
}
}
}
catch (error) {
logError(error);
}
return hash.digest('hex');
};
export const useHashCheck = async (PEER_IP, PEER_TCP_PORT, FILE_ID, FILENAME) => {
log('Hash checking:', FILENAME);
try {
const url = `http://${PEER_IP}:${PEER_TCP_PORT}/get-hash/${FILE_ID}`;
const outputPath = path.join(RECEIVE_PATH, FILENAME);
updateTransferFileState(FILE_ID, 'HASH_CHECKING');
await fetchUpdateSenderTransferState(PEER_IP, PEER_TCP_PORT, FILE_ID, 'HASH_CHECKING');
const response = await fetch(url);
if (!response.ok) {
const errorText = await response.text();
logError(`Error: ${response.status} - ${errorText}`);
throw new Error(`Fetch failed with status ${response.status}`);
}
const data = await response.json();
const sendFileHash = data.hash;
const stats = fs.statSync(outputPath);
const receivedFileHash = stats.isDirectory()
? await hashFolder(outputPath)
: await hashFile(outputPath);
if (sendFileHash === receivedFileHash) {
log('HASH MATCHED');
updateTransferFileState(FILE_ID, 'SUCCESS');
await fetchUpdateSenderTransferState(PEER_IP, PEER_TCP_PORT, FILE_ID, 'SUCCESS');
}
else {
log("HASH DIDN'T MATCH", sendFileHash, receivedFileHash);
throw new Error('Hash Mismatch.');
}
}
catch (error) {
let errMsg = 'Error during hash check';
if (error instanceof Error) {
errMsg = error.message;
}
updateTransferFileState(FILE_ID, 'ERROR');
updateTransferFileErrorMsg(FILE_ID, errMsg);
await fetchUpdateSenderTransferState(PEER_IP, PEER_TCP_PORT, FILE_ID, 'ERROR', errMsg);
logError('Error during hash check:', error);
throw error;
}
};