2022-11-11 12:02:22 +01:00
|
|
|
#include "UpdaterState.h"
|
|
|
|
#include "utils/DownloadUtils.h"
|
|
|
|
#include "utils/FSUtils.h"
|
|
|
|
#include "utils/logger.h"
|
|
|
|
#include "utils/zip_file.hpp"
|
|
|
|
#include <coreinit/cache.h>
|
|
|
|
#include <coreinit/thread.h>
|
|
|
|
#include <mutex>
|
|
|
|
|
|
|
|
int DownloadFilesThreadEntry(UpdaterState *updater) {
|
|
|
|
std::lock_guard<std::mutex> lock(updater->mFilesDownloadListLock);
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lockInfo(updater->mDownloadInfosLock);
|
|
|
|
updater->mDownloadInfos = DownloadInfos(updater->mFilesDownloadList.size());
|
|
|
|
}
|
|
|
|
for (auto &curFile : updater->mFilesDownloadList) {
|
|
|
|
DEBUG_FUNCTION_LINE("Download and extract %s", curFile.getPath().c_str());
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lockInfo(updater->mDownloadInfosLock);
|
|
|
|
updater->mDownloadInfos->curFile = curFile;
|
|
|
|
updater->mDownloadInfos->processStep = DownloadInfos::STEP_DOWNLOAD;
|
|
|
|
}
|
|
|
|
OSMemoryBarrier();
|
|
|
|
auto &curURL = curFile.getAsset().getBrowserDownloadUrl();
|
|
|
|
DEBUG_FUNCTION_LINE("Check if %s is in cache", curURL.c_str());
|
|
|
|
if (!updater->mZipDownloadCache.contains(curURL)) {
|
|
|
|
std::string downloadedZIP;
|
|
|
|
int responseCode;
|
|
|
|
updater->mProgress = 0.0f;
|
|
|
|
DEBUG_FUNCTION_LINE("Download %s", curURL.c_str());
|
2023-01-18 21:33:10 +01:00
|
|
|
int errorCode;
|
|
|
|
std::string errorText;
|
|
|
|
if (DownloadUtils::DownloadFileToBuffer(curURL, downloadedZIP, responseCode, errorCode, errorText, &updater->mProgress) < 0 || responseCode != 200) {
|
2023-01-18 21:33:19 +01:00
|
|
|
DEBUG_FUNCTION_LINE_ERR("Download failed for %s. curl error code %d, error text %s, response code: %d", curURL.c_str(), errorCode, errorText.c_str(), responseCode);
|
2022-11-11 12:02:22 +01:00
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lockInfo(updater->mDownloadInfosLock);
|
2023-01-18 21:33:10 +01:00
|
|
|
updater->mDownloadInfos->state = DownloadInfos::DOWNLOAD_FAILED;
|
|
|
|
updater->mDownloadInfos->errorCode = errorCode;
|
|
|
|
updater->mDownloadInfos->errorText = errorText;
|
|
|
|
updater->mDownloadInfos->responseCode = responseCode;
|
2022-11-11 12:02:22 +01:00
|
|
|
OSMemoryBarrier();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
updater->mZipDownloadCache[curURL] = downloadedZIP;
|
|
|
|
} else {
|
|
|
|
DEBUG_FUNCTION_LINE("Use cached version.");
|
|
|
|
}
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lockInfo(updater->mDownloadInfosLock);
|
|
|
|
updater->mDownloadInfos->processStep = DownloadInfos::STEP_EXTRACT;
|
|
|
|
}
|
|
|
|
auto &curBuffer = updater->mZipDownloadCache[curURL];
|
|
|
|
std::istringstream iss(curBuffer);
|
|
|
|
miniz_cpp::zip_file zip(iss);
|
|
|
|
|
|
|
|
bool found = false;
|
|
|
|
// find asset
|
|
|
|
for (auto &assetFile : curFile.getAsset().getFiles()) {
|
|
|
|
if (assetFile.getSha1() == curFile.getSha1()) {
|
|
|
|
for (auto &member : zip.infolist()) {
|
|
|
|
if (member.filename == assetFile.getPath()) {
|
|
|
|
found = true;
|
|
|
|
auto fullPath = SD_PATH + curFile.getPath() + UPDATE_TEMP_SUFFIX;
|
|
|
|
std::filesystem::path path = fullPath;
|
|
|
|
|
|
|
|
if (CreateSubfolder(path.remove_filename().c_str()) == 0) {
|
|
|
|
std::lock_guard<std::mutex> lockInfo(updater->mDownloadInfosLock);
|
|
|
|
updater->mDownloadInfos->state = DownloadInfos::DOWNLOAD_CREATE_DIR_FAILED;
|
|
|
|
OSMemoryBarrier();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
DEBUG_FUNCTION_LINE("Extract %s to %s", member.filename.c_str(), fullPath.c_str());
|
|
|
|
std::string ss = zip.read(member);
|
|
|
|
if (saveBufferToFile(fullPath.c_str(), (void *) ss.c_str(), ss.length()) < 0) {
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lockInfo(updater->mDownloadInfosLock);
|
|
|
|
updater->mDownloadInfos->state = DownloadInfos::DOWNLOAD_EXTRACT_FAILED;
|
|
|
|
OSMemoryBarrier();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DEBUG_FUNCTION_LINE("Extract done");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
2023-01-18 21:33:19 +01:00
|
|
|
DEBUG_FUNCTION_LINE_ERR("Failed to find with hash %s in zip (%s)", curFile.getSha1().c_str(), curURL.c_str());
|
2022-11-11 12:02:22 +01:00
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lockInfo(updater->mDownloadInfosLock);
|
|
|
|
updater->mDownloadInfos->state = DownloadInfos::DOWNLOAD_NOT_FOUND_IN_ZIP;
|
|
|
|
OSMemoryBarrier();
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lockInfo(updater->mDownloadInfosLock);
|
|
|
|
updater->mDownloadInfos->filesDone++;
|
|
|
|
OSMemoryBarrier();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lockInfo(updater->mDownloadInfosLock);
|
|
|
|
updater->mDownloadInfos->state = DownloadInfos::DOWNLOAD_SUCCESS;
|
|
|
|
OSMemoryBarrier();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ApplicationState::eSubState UpdaterState::UpdateProcessDownloadFiles(Input *input) {
|
|
|
|
if (mDownloadFilesThread == nullptr) {
|
|
|
|
OSMemoryBarrier();
|
|
|
|
mDownloadFilesThread = new (std::nothrow) std::thread(DownloadFilesThreadEntry, this);
|
|
|
|
if (mDownloadFilesThread == nullptr) {
|
|
|
|
setError(ERROR_FAILED_TO_CREATE_THREAD);
|
|
|
|
return ApplicationState::SUBSTATE_RUNNING;
|
|
|
|
}
|
|
|
|
auto nativeHandle = (OSThread *) mDownloadFilesThread->native_handle();
|
|
|
|
OSSetThreadName(nativeHandle, "DownloadFilesThread");
|
|
|
|
return ApplicationState::SUBSTATE_RUNNING;
|
|
|
|
}
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lockInfo(this->mDownloadInfosLock);
|
|
|
|
if (!this->mDownloadInfos.has_value() || mDownloadInfos->state == DownloadInfos::DOWNLOAD_RUNNING) {
|
|
|
|
return ApplicationState::SUBSTATE_RUNNING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mDownloadFilesThread->join();
|
|
|
|
delete mDownloadFilesThread;
|
|
|
|
mDownloadFilesThread = nullptr;
|
|
|
|
OSMemoryBarrier();
|
|
|
|
|
|
|
|
switch (mDownloadInfos->state) {
|
|
|
|
case DownloadInfos::DOWNLOAD_RUNNING:
|
|
|
|
setError(ERROR_UNKNOWN);
|
|
|
|
break;
|
|
|
|
case DownloadInfos::DOWNLOAD_SUCCESS:
|
|
|
|
this->mState = STATE_UPDATE_PROCESS_DOWNLOAD_FILES_FINISHED;
|
|
|
|
break;
|
|
|
|
case DownloadInfos::DOWNLOAD_FAILED:
|
2023-01-18 21:33:10 +01:00
|
|
|
if (this->mDownloadInfos) {
|
|
|
|
this->mResponseCode = this->mDownloadInfos->responseCode;
|
|
|
|
this->mDownloadErrorCode = this->mDownloadInfos->errorCode;
|
|
|
|
this->mDownloadErrorText = this->mDownloadInfos->errorText;
|
|
|
|
}
|
2022-11-11 12:02:22 +01:00
|
|
|
setError(ERROR_DOWNLOAD_FAILED);
|
|
|
|
break;
|
|
|
|
case DownloadInfos::DOWNLOAD_EXTRACT_FAILED:
|
|
|
|
setError(ERROR_EXTRACT_FAILED);
|
|
|
|
break;
|
|
|
|
case DownloadInfos::DOWNLOAD_NOT_FOUND_IN_ZIP:
|
|
|
|
setError(ERROR_FAILED_TO_FIND_FILE_IN_ZIP);
|
|
|
|
break;
|
|
|
|
case DownloadInfos::DOWNLOAD_CREATE_DIR_FAILED:
|
|
|
|
setError(ERROR_FAILED_TO_CREATE_DIR);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ApplicationState::SUBSTATE_RUNNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdaterState::RenderProcessDownloadFiles() {
|
|
|
|
DrawUtils::setFontColor(COLOR_WHITE);
|
|
|
|
DrawUtils::setFontSize(20);
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lock(mDownloadInfosLock);
|
|
|
|
if (mDownloadInfos.has_value()) {
|
|
|
|
DrawUtils::printf(16, 80, false, "Downloading and extracting files... %s", this->mLoadAnimation[mAnimationTick++ % this->mLoadAnimation.size()].c_str());
|
|
|
|
if (mDownloadInfos->curFile.has_value()) {
|
|
|
|
DrawUtils::printf(16, 100, false, "File: %s", mDownloadInfos->curFile->getPath().c_str());
|
|
|
|
if (mDownloadInfos->processStep == DownloadInfos::STEP_DOWNLOAD) {
|
|
|
|
if (this->mProgress > 0.0f) {
|
|
|
|
DrawUtils::printf(16, 120, false, "Downloading... %.0f%%", this->mProgress * 100.0f);
|
|
|
|
} else {
|
|
|
|
DrawUtils::printf(16, 120, false, "Downloading...");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
DrawUtils::printf(16, 120, false, "Extracting...", mDownloadInfos->curFile->getPath().c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DrawUtils::printf(16, 160, false, "%d of %d files done.", mDownloadInfos->filesDone, mDownloadInfos->totalFiles);
|
|
|
|
} else {
|
|
|
|
DrawUtils::printf(16, 80, false, "Preparing download of files...");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|