diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 68fd5f7b7..58bd57a87 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -584,6 +584,7 @@ set(PRISMUPDATER_SOURCES updater/prismupdater/UpdaterDialogs.h updater/prismupdater/UpdaterDialogs.cpp updater/prismupdater/GitHubRelease.h + Json.h Json.cpp FileSystem.h @@ -595,6 +596,31 @@ set(PRISMUPDATER_SOURCES Version.h Version.cpp Markdown.h + + # Time + MMCTime.h + MMCTime.cpp + + + net/ByteArraySink.h + net/ChecksumValidator.h + net/Download.cpp + net/Download.h + net/FileSink.cpp + net/FileSink.h + net/HttpMetaCache.cpp + net/HttpMetaCache.h + net/Logging.h + net/Logging.cpp + net/NetAction.h + net/NetJob.cpp + net/NetJob.h + net/NetUtils.h + net/Sink.h + net/Validator.h + net/HeaderProxy.h + net/RawHeaderProxy.h + ) ######## Logging categories ######## @@ -1125,6 +1151,7 @@ endif() add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES}) target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION) target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION) target_link_libraries(Launcher_logic systeminfo Launcher_murmur2 @@ -1202,7 +1229,7 @@ install(TARGETS ${Launcher_Name} if(WIN32 OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) ) # Updater - add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${PRISMUPDATER_UI}) + add_library(prism_updater_logic STATIC ${PRISMUPDATER_SOURCES} ${TASKS_SOURCES} ${PRISMUPDATER_UI}) target_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(prism_updater_logic systeminfo @@ -1213,6 +1240,7 @@ if(WIN32 OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) ) Qt${QT_VERSION_MAJOR}::Network ${Launcher_QT_LIBS} cmark::cmark + Katabasis ) add_executable("${Launcher_Name}_updater" WIN32 updater/prismupdater/updater_main.cpp) diff --git a/launcher/net/Download.cpp b/launcher/net/Download.cpp index c86452137..de6f43380 100644 --- a/launcher/net/Download.cpp +++ b/launcher/net/Download.cpp @@ -131,13 +131,12 @@ void Download::executeTask() return; } -#if defined (LAUNCHER_APPLICATION) - auto user_agent = APPLICATION->getUserAgent(); +#if defined(LAUNCHER_APPLICATION) + auto user_agent = APPLICATION->getUserAgent().toUtf8(); #else - auto user_agent = BuildConfig.USER_AGENT; + auto user_agent = BuildConfig.USER_AGENT.toUtf8(); #endif - - request.setHeader(QNetworkRequest::UserAgentHeader, user_agent.toUtf8()); + request.setHeader(QNetworkRequest::UserAgentHeader, user_agent); for ( auto& header_proxy : m_headerProxies ) { header_proxy->writeHeaders(request); diff --git a/launcher/net/Download.h b/launcher/net/Download.h index 19f675adc..65141a04c 100644 --- a/launcher/net/Download.h +++ b/launcher/net/Download.h @@ -59,6 +59,7 @@ class Download : public NetAction { public: ~Download() override = default; + #if defined(LAUNCHER_APPLICATION) static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr; static auto makeByteArray(QUrl url, std::shared_ptr output, Options options = Option::NoOptions) -> Download::Ptr; static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr; diff --git a/launcher/updater/prismupdater/PrismUpdater.cpp b/launcher/updater/prismupdater/PrismUpdater.cpp index 923b891f9..0e6620085 100644 --- a/launcher/updater/prismupdater/PrismUpdater.cpp +++ b/launcher/updater/prismupdater/PrismUpdater.cpp @@ -34,7 +34,9 @@ #include #include +#include #include +#include #include #include @@ -74,6 +76,9 @@ namespace fs = ghc::filesystem; #include "Json.h" #include "StringUtils.h" +#include "net/Download.h" +#include "net/RawHeaderProxy.h" + /** output to the log file */ void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) { @@ -205,8 +210,7 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar } #endif } - m_network = new QNetworkAccessManager(); - + { // setup logging static const QString logBase = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log"; auto moveFile = [](const QString& oldName, const QString& newName) { @@ -292,6 +296,8 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar qDebug() << "<> Log initialized."; } + + { // log debug program info qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME) << "Updater" << ", (c) 2022-2023 " << qPrintable(QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", ")); @@ -310,7 +316,14 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar qDebug() << "<> Paths set."; } - loadReleaseList(); + { // network + m_network = makeShared(new QNetworkAccessManager()); + qDebug() << "Detecting proxy settings..."; + QNetworkProxy proxy = QNetworkProxy::applicationProxy(); + m_network->setProxy(proxy); + } + + QMetaObject::invokeMethod(this, &PrismUpdaterApp::loadReleaseList, Qt::QueuedConnection); } PrismUpdaterApp::~PrismUpdaterApp() @@ -329,9 +342,6 @@ PrismUpdaterApp::~PrismUpdaterApp() } #endif - m_network->deleteLater(); - if (m_reply) - m_reply->deleteLater(); } void PrismUpdaterApp::fail(const QString& reason) @@ -460,7 +470,7 @@ GitHubRelease PrismUpdaterApp::selectRelease() } else { releases = newerReleases(); } - + if (releases.isEmpty()) return {}; @@ -530,34 +540,40 @@ void PrismUpdaterApp::downloadReleasePage(const QString& api_url, int page) { int per_page = 30; auto page_url = QString("%1?per_page=%2&page=%3").arg(api_url).arg(QString::number(per_page)).arg(QString::number(page)); - QNetworkRequest request(page_url); - request.setRawHeader("Accept", "application/vnd.github+json"); - request.setRawHeader("X-GitHub-Api-Version", "2022-11-28"); + auto responce = std::make_shared(); + auto download = Net::Download::makeByteArray(page_url, responce.get()); + download->setNetwork(m_network); + m_current_url = page_url; - QNetworkReply* rep = m_network->get(request); - m_reply = rep; - auto responce = new QByteArray(); - - connect(rep, &QNetworkReply::finished, this, [this, responce, per_page, api_url, page]() { - int num_found = parseReleasePage(responce); - delete responce; + auto githup_api_headers = new Net::RawHeaderProxy(); + githup_api_headers->addHeaders({ + { "Accept", "application/vnd.github+json" }, + { "X-GitHub-Api-Version", "2022-11-28" }, + }); + download->addHeaderProxy(githup_api_headers); + connect(download.get(), &Net::Download::succeeded, this, [this, responce, per_page, api_url, page]() { + int num_found = parseReleasePage(responce.get()); if (!(num_found < per_page)) { // there may be more, fetch next page downloadReleasePage(api_url, page + 1); } else { run(); } }); -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 - connect(rep, &QNetworkReply::errorOccurred, this, &PrismUpdaterApp::downloadError); -#else - connect(rep, QOverload::of(&QNetworkReply::error), this, &WindowsUpdaterApp::downloadError); -#endif - connect(rep, &QNetworkReply::sslErrors, this, &PrismUpdaterApp::sslErrors); - connect(rep, &QNetworkReply::readyRead, this, [this, responce]() { - auto data = m_reply->readAll(); - responce->append(data); + connect(download.get(), &Net::Download::failed, this, &PrismUpdaterApp::downloadError); + + + m_current_task.reset(download); + connect(download.get(), &Net::Download::finished, this, [this](){ + qDebug() << "Download" << m_current_task->getUid().toString() << "finsihed"; + m_current_task.reset(); + m_current_url = ""; }); + + + QCoreApplication::processEvents(); + + QMetaObject::invokeMethod(download.get(), &Task::start, Qt::QueuedConnection); } int PrismUpdaterApp::parseReleasePage(const QByteArray* responce) @@ -624,24 +640,7 @@ bool PrismUpdaterApp::needUpdate(const GitHubRelease& release) return current_ver < release.version; } -void PrismUpdaterApp::downloadError(QNetworkReply::NetworkError error) +void PrismUpdaterApp::downloadError(QString reason) { - if (error == QNetworkReply::OperationCanceledError) { - abort(QString("Aborted %1").arg(m_reply->url().toString())); - } else { - fail(QString("Network request Failed: %1 with reason %2").arg(m_reply->url().toString()).arg(error)); - } -} - -void PrismUpdaterApp::sslErrors(const QList& errors) -{ - int i = 1; - QString err_msg; - for (auto error : errors) { - err_msg.append(QString("Network request %1 SSL Error %2: %3\n").arg(m_reply->url().toString()).arg(i).arg(error.errorString())); - auto cert = error.certificate(); - err_msg.append(QString("Certificate in question:\n%1").arg(cert.toText())); - i++; - } - fail(err_msg); + fail(QString("Network request Failed: %1 with reason %2").arg(m_current_url).arg(reason)); } diff --git a/launcher/updater/prismupdater/PrismUpdater.h b/launcher/updater/prismupdater/PrismUpdater.h index da6b4bf71..52bb7e71b 100644 --- a/launcher/updater/prismupdater/PrismUpdater.h +++ b/launcher/updater/prismupdater/PrismUpdater.h @@ -36,6 +36,10 @@ #include #include +#include "QObjectPtr.h" +#include "net/Download.h" + + #define PRISM_EXTERNAL_EXE #include "FileSystem.h" @@ -58,7 +62,7 @@ class PrismUpdaterApp : public QApplication { void showFatalErrorMessage(const QString& title, const QString& content); void loadPrismVersionFromExe(const QString& exe_path); - + void downloadReleasePage(const QString& api_url, int page); int parseReleasePage(const QByteArray* responce); GitHubRelease getLatestRelease(); @@ -69,8 +73,10 @@ class PrismUpdaterApp : public QApplication { QList newerReleases(); QList nonDraftReleases(); - void downloadError(QNetworkReply::NetworkError error); - void sslErrors(const QList& errors); + public slots: + void downloadError(QString reason); + + private: const QString& root() { return m_rootPath; } @@ -95,8 +101,9 @@ class PrismUpdaterApp : public QApplication { QString m_prismGitCommit; Status m_status = Status::Starting; - QNetworkAccessManager* m_network; - QNetworkReply* m_reply; + shared_qobject_ptr m_network; + QString m_current_url; + Task::Ptr m_current_task; QList m_releases; public: