added async hash checking

This commit is contained in:
FinnHornhoover 2023-09-24 00:48:01 +03:00
parent b644edb774
commit 2c5337938a
2 changed files with 128 additions and 50 deletions

View File

@ -13,6 +13,11 @@ var configPath = path.join(userData, "config.json");
var serversPath = path.join(userData, "servers.json"); var serversPath = path.join(userData, "servers.json");
var versionsPath = path.join(userData, "versions.json"); var versionsPath = path.join(userData, "versions.json");
var hashPath = path.join(userData, "hash.txt"); var hashPath = path.join(userData, "hash.txt");
var cacheRoot = path.join(
userData,
"/../../LocalLow/Unity/Web Player/Cache"
);
var offlineRoot = path.join(cacheRoot, "Offline");
var chunkSize = 1 << 16; var chunkSize = 1 << 16;
var gb = 1 << 30; var gb = 1 << 30;
@ -492,17 +497,22 @@ function loadCacheList() {
$("#cache-tablebody").append(row); $("#cache-tablebody").append(row);
checkPlayableCache(value.name); ipc.send("hash-check", {
checkOfflineCache(value.name); localDir: cacheRoot,
cacheMode: "playable",
versionString: value.name,
hashes: versionHashes.playable[value.name],
});
ipc.send("hash-check", {
localDir: offlineRoot,
cacheMode: "offline",
versionString: value.name,
hashes: versionHashes.offline[value.name],
});
}) })
} }
function deletePlayableCache(versionString) { function deletePlayableCache(versionString) {
var cacheRoot = path.join(
userData,
"/../../LocalLow/Unity/Web Player/Cache"
);
resetCacheNames(); resetCacheNames();
if (versionString === "Offline") { if (versionString === "Offline") {
@ -516,11 +526,6 @@ function deletePlayableCache(versionString) {
} }
function downloadOfflineCache(versionString) { function downloadOfflineCache(versionString) {
var offlineRoot = path.join(
userData,
"/../../LocalLow/Unity/Web Player/Cache/Offline"
);
var buttonDownload = document.getElementById(getCacheButtonID(versionString, "offline", "download")); var buttonDownload = document.getElementById(getCacheButtonID(versionString, "offline", "download"));
var buttonFix = document.getElementById(getCacheButtonID(versionString, "offline", "fix")); var buttonFix = document.getElementById(getCacheButtonID(versionString, "offline", "fix"));
var buttonDelete = document.getElementById(getCacheButtonID(versionString, "offline", "delete")); var buttonDelete = document.getElementById(getCacheButtonID(versionString, "offline", "delete"));
@ -582,11 +587,6 @@ function downloadOfflineCache(versionString) {
} }
function deleteOfflineCache(versionString) { function deleteOfflineCache(versionString) {
var offlineRoot = path.join(
userData,
"/../../LocalLow/Unity/Web Player/Cache/Offline"
);
remotefs.removeSync(path.join(offlineRoot, versionString)); remotefs.removeSync(path.join(offlineRoot, versionString));
console.log("Offline cache " + versionString + " has been removed!"); console.log("Offline cache " + versionString + " has been removed!");
@ -594,11 +594,6 @@ function deleteOfflineCache(versionString) {
} }
function checkPlayableCache(versionString) { function checkPlayableCache(versionString) {
var cacheRoot = path.join(
userData,
"/../../LocalLow/Unity/Web Player/Cache"
);
var button = document.getElementById(getCacheButtonID(versionString, "playable", "delete")); var button = document.getElementById(getCacheButtonID(versionString, "playable", "delete"));
var label = document.getElementById(getCacheElemID(versionString, "playable", "label")); var label = document.getElementById(getCacheElemID(versionString, "playable", "label"));
@ -630,11 +625,6 @@ function checkPlayableCache(versionString) {
} }
function checkOfflineCache(versionString) { function checkOfflineCache(versionString) {
var offlineRoot = path.join(
userData,
"/../../LocalLow/Unity/Web Player/Cache/Offline"
);
var buttonDownload = document.getElementById(getCacheButtonID(versionString, "offline", "download")); var buttonDownload = document.getElementById(getCacheButtonID(versionString, "offline", "download"));
var buttonFix = document.getElementById(getCacheButtonID(versionString, "offline", "fix")); var buttonFix = document.getElementById(getCacheButtonID(versionString, "offline", "fix"));
var buttonDelete = document.getElementById(getCacheButtonID(versionString, "offline", "delete")); var buttonDelete = document.getElementById(getCacheButtonID(versionString, "offline", "delete"));
@ -674,10 +664,6 @@ function checkOfflineCache(versionString) {
} }
function resetCacheNames() { function resetCacheNames() {
var cacheRoot = path.join(
userData,
"/../../LocalLow/Unity/Web Player/Cache"
);
var currentCache = path.join(cacheRoot, "Fusionfall"); var currentCache = path.join(cacheRoot, "Fusionfall");
var record = path.join(userData, ".lastver"); var record = path.join(userData, ".lastver");
@ -694,10 +680,6 @@ function resetCacheNames() {
} }
function performCacheSwap(newVersion) { function performCacheSwap(newVersion) {
var cacheRoot = path.join(
userData,
"/../../LocalLow/Unity/Web Player/Cache"
);
var currentCache = path.join(cacheRoot, "FusionFall"); var currentCache = path.join(cacheRoot, "FusionFall");
var newCache = path.join(cacheRoot, newVersion); var newCache = path.join(cacheRoot, newVersion);
var record = path.join(userData, ".lastver"); var record = path.join(userData, ".lastver");
@ -910,3 +892,18 @@ ipc.on("download-success", function (versionString) {
buttonFix.children[0].setAttribute("class", "fas fa-hammer"); buttonFix.children[0].setAttribute("class", "fas fa-hammer");
checkOfflineCache(versionString); checkOfflineCache(versionString);
}); });
ipc.on("hash-update", function (arg) {
var sizes = versionSizes[arg.cacheMode][arg.versionString];
if (arg.sizes) {
sizes.intact += arg.sizes.intact;
sizes.altered += arg.sizes.altered;
} else {
sizes.intact = 0;
sizes.altered = 0;
}
var label = document.getElementById(getCacheElemID(arg.versionString, arg.cacheMode, "label"));
label.innerHTML = getCacheLabelText(sizes);
});

111
index.js
View File

@ -7,6 +7,7 @@ var path = require("path");
var url = require("url"); var url = require("url");
var http = require("http"); var http = require("http");
var async = require("async"); var async = require("async");
var createHash = require("crypto").createHash;
var BrowserWindow = require("browser-window"); var BrowserWindow = require("browser-window");
var mainWindow = null; var mainWindow = null;
@ -122,6 +123,39 @@ app.on("ready", function () {
mainWindow.on("closed", function () { mainWindow.on("closed", function () {
mainWindow = null; mainWindow = null;
}); });
ipc.on("download-files", function (event, arg) {
downloadFiles(
arg.nginxDir,
arg.localDir,
arg.fileRelativePaths,
function (size) {
mainWindow.webContents.send("download-update", {
size: size,
versionString: arg.versionString,
});
},
function () {
mainWindow.webContents.send("download-success", arg.versionString);
}
);
});
ipc.on("hash-check", function (event, arg) {
mainWindow.webContents.send("hash-update", {
cacheMode: arg.cacheMode,
versionString: arg.versionString,
// no size sent, reset sizes
});
checkHashes(arg.localDir, arg.hashes, function (sizes) {
mainWindow.webContents.send("hash-update", {
cacheMode: arg.cacheMode,
versionString: arg.versionString,
sizes: sizes,
});
});
});
}); });
function showMainWindow() { function showMainWindow() {
@ -239,10 +273,10 @@ function downloadFiles(nginxDir, localDir, fileRelativePaths, updateCallback, al
async.eachLimit( async.eachLimit(
fileRelativePaths, fileRelativePaths,
5, // Number of parallel downloads 5, // Number of parallel downloads
function(relativePath, callback) { function (relativePath, callback) {
downloadFile(nginxDir, localDir, relativePath, callback, updateCallback); downloadFile(nginxDir, localDir, relativePath, callback, updateCallback);
}, },
function(err) { function (err) {
if (err) { if (err) {
console.error("Download failed: " + err); console.error("Download failed: " + err);
} else { } else {
@ -253,19 +287,66 @@ function downloadFiles(nginxDir, localDir, fileRelativePaths, updateCallback, al
); );
} }
ipc.on("download-files", function (event, arg) { function checkHash(localDir, relativePath, fileHash, callback, updateCallback) {
downloadFiles( var localPath = path.join(localDir, relativePath);
arg.nginxDir,
arg.localDir, var chunkSize = 1 << 16;
arg.fileRelativePaths, var totalCount = 0;
function (size) { var buff = new Buffer(chunkSize);
mainWindow.webContents.send("download-update", { var hash = createHash("sha256");
size: size,
versionString: arg.versionString, fs.open(localPath, "r", function (openErr, file) {
}); if (openErr) {
if (openErr.code !== "ENOENT") {
console.log("Error opening file for hash check: " + openErr);
}
return;
}
var updater;
var reader = function () {
fs.read(file, buff, 0, chunkSize, null, updater);
};
updater = function (readErr, readSize) {
if (readErr) {
console.log("Error reading file for hash check: " + readErr);
} else if (readSize > 0) {
hash.update(buff.slice(0, readSize));
totalCount += readSize;
reader();
} else {
var state = (fileHash === hash.digest(encoding="hex")) ? "intact" : "altered";
var sizes = { intact: 0, altered: 0 };
sizes[state] = totalCount;
fs.close(file, function (fileCloseErr) {
if (fileCloseErr) {
console.log("Error closing file for hash check: " + fileCloseErr);
} else {
callback(null, relativePath);
updateCallback(sizes);
}
});
}
};
reader();
});
}
function checkHashes(localDir, hashes, updateCallback) {
console.log(hashes);
async.eachLimit(
Object.keys(hashes),
20,
function (relativePath, callback) {
checkHash(localDir, relativePath, hashes[relativePath], callback, updateCallback);
}, },
function () { function (err) {
mainWindow.webContents.send("download-success", arg.versionString); if (err) {
console.log("Hash check failed: " + err);
}
} }
); );
}); }