refactor: use Net tasks for github api download

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
Rachel Powers 2023-06-02 15:15:25 -07:00
parent 5d03919b59
commit 98174b7a37
No known key found for this signature in database
GPG Key ID: E10E321EB160949B
5 changed files with 90 additions and 56 deletions

View File

@ -584,6 +584,7 @@ set(PRISMUPDATER_SOURCES
updater/prismupdater/UpdaterDialogs.h updater/prismupdater/UpdaterDialogs.h
updater/prismupdater/UpdaterDialogs.cpp updater/prismupdater/UpdaterDialogs.cpp
updater/prismupdater/GitHubRelease.h updater/prismupdater/GitHubRelease.h
Json.h Json.h
Json.cpp Json.cpp
FileSystem.h FileSystem.h
@ -595,6 +596,31 @@ set(PRISMUPDATER_SOURCES
Version.h Version.h
Version.cpp Version.cpp
Markdown.h 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 ######## ######## Logging categories ########
@ -1125,6 +1151,7 @@ endif()
add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES}) add_library(Launcher_logic STATIC ${LOGIC_SOURCES} ${LAUNCHER_SOURCES} ${LAUNCHER_UI} ${LAUNCHER_RESOURCES})
target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION) target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION)
target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(Launcher_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(Launcher_logic PUBLIC LAUNCHER_APPLICATION)
target_link_libraries(Launcher_logic target_link_libraries(Launcher_logic
systeminfo systeminfo
Launcher_murmur2 Launcher_murmur2
@ -1202,7 +1229,7 @@ install(TARGETS ${Launcher_Name}
if(WIN32 OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) ) if(WIN32 OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) )
# 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_include_directories(prism_updater_logic PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(prism_updater_logic target_link_libraries(prism_updater_logic
systeminfo systeminfo
@ -1213,6 +1240,7 @@ if(WIN32 OR (DEFINED Launcher_BUILD_UPDATER AND Launcher_BUILD_UPDATER) )
Qt${QT_VERSION_MAJOR}::Network Qt${QT_VERSION_MAJOR}::Network
${Launcher_QT_LIBS} ${Launcher_QT_LIBS}
cmark::cmark cmark::cmark
Katabasis
) )
add_executable("${Launcher_Name}_updater" WIN32 updater/prismupdater/updater_main.cpp) add_executable("${Launcher_Name}_updater" WIN32 updater/prismupdater/updater_main.cpp)

View File

@ -131,13 +131,12 @@ void Download::executeTask()
return; return;
} }
#if defined (LAUNCHER_APPLICATION) #if defined(LAUNCHER_APPLICATION)
auto user_agent = APPLICATION->getUserAgent(); auto user_agent = APPLICATION->getUserAgent().toUtf8();
#else #else
auto user_agent = BuildConfig.USER_AGENT; auto user_agent = BuildConfig.USER_AGENT.toUtf8();
#endif #endif
request.setHeader(QNetworkRequest::UserAgentHeader, user_agent);
request.setHeader(QNetworkRequest::UserAgentHeader, user_agent.toUtf8());
for ( auto& header_proxy : m_headerProxies ) { for ( auto& header_proxy : m_headerProxies ) {
header_proxy->writeHeaders(request); header_proxy->writeHeaders(request);

View File

@ -59,6 +59,7 @@ class Download : public NetAction {
public: public:
~Download() override = default; ~Download() override = default;
#if defined(LAUNCHER_APPLICATION)
static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr; static auto makeCached(QUrl url, MetaEntryPtr entry, Options options = Option::NoOptions) -> Download::Ptr;
static auto makeByteArray(QUrl url, std::shared_ptr<QByteArray> output, Options options = Option::NoOptions) -> Download::Ptr; static auto makeByteArray(QUrl url, std::shared_ptr<QByteArray> output, Options options = Option::NoOptions) -> Download::Ptr;
static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr; static auto makeFile(QUrl url, QString path, Options options = Option::NoOptions) -> Download::Ptr;

View File

@ -34,7 +34,9 @@
#include <QMessageBox> #include <QMessageBox>
#include <QNetworkRequest> #include <QNetworkRequest>
#include <QNetworkProxy>
#include <QProcess> #include <QProcess>
#include <memory>
#include <qglobal.h> #include <qglobal.h>
#include <sys.h> #include <sys.h>
@ -74,6 +76,9 @@ namespace fs = ghc::filesystem;
#include "Json.h" #include "Json.h"
#include "StringUtils.h" #include "StringUtils.h"
#include "net/Download.h"
#include "net/RawHeaderProxy.h"
/** output to the log file */ /** output to the log file */
void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg) void appDebugOutput(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{ {
@ -205,7 +210,6 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
} }
#endif #endif
} }
m_network = new QNetworkAccessManager();
{ // setup logging { // setup logging
static const QString logBase = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log"; static const QString logBase = BuildConfig.LAUNCHER_NAME + "Updater" + (m_checkOnly ? "-CheckOnly" : "") + "-%0.log";
@ -292,6 +296,8 @@ PrismUpdaterApp::PrismUpdaterApp(int& argc, char** argv) : QApplication(argc, ar
qDebug() << "<> Log initialized."; qDebug() << "<> Log initialized.";
} }
{ // log debug program info { // log debug program info
qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME) << "Updater" qDebug() << qPrintable(BuildConfig.LAUNCHER_DISPLAYNAME) << "Updater"
<< ", (c) 2022-2023 " << qPrintable(QString(BuildConfig.LAUNCHER_COPYRIGHT).replace("\n", ", ")); << ", (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."; qDebug() << "<> Paths set.";
} }
loadReleaseList(); { // network
m_network = makeShared<QNetworkAccessManager>(new QNetworkAccessManager());
qDebug() << "Detecting proxy settings...";
QNetworkProxy proxy = QNetworkProxy::applicationProxy();
m_network->setProxy(proxy);
}
QMetaObject::invokeMethod(this, &PrismUpdaterApp::loadReleaseList, Qt::QueuedConnection);
} }
PrismUpdaterApp::~PrismUpdaterApp() PrismUpdaterApp::~PrismUpdaterApp()
@ -329,9 +342,6 @@ PrismUpdaterApp::~PrismUpdaterApp()
} }
#endif #endif
m_network->deleteLater();
if (m_reply)
m_reply->deleteLater();
} }
void PrismUpdaterApp::fail(const QString& reason) void PrismUpdaterApp::fail(const QString& reason)
@ -530,34 +540,40 @@ void PrismUpdaterApp::downloadReleasePage(const QString& api_url, int page)
{ {
int per_page = 30; 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)); 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); auto responce = std::make_shared<QByteArray>();
request.setRawHeader("Accept", "application/vnd.github+json"); auto download = Net::Download::makeByteArray(page_url, responce.get());
request.setRawHeader("X-GitHub-Api-Version", "2022-11-28"); download->setNetwork(m_network);
m_current_url = page_url;
QNetworkReply* rep = m_network->get(request); auto githup_api_headers = new Net::RawHeaderProxy();
m_reply = rep; githup_api_headers->addHeaders({
auto responce = new QByteArray(); { "Accept", "application/vnd.github+json" },
{ "X-GitHub-Api-Version", "2022-11-28" },
connect(rep, &QNetworkReply::finished, this, [this, responce, per_page, api_url, page]() { });
int num_found = parseReleasePage(responce); download->addHeaderProxy(githup_api_headers);
delete responce;
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 if (!(num_found < per_page)) { // there may be more, fetch next page
downloadReleasePage(api_url, page + 1); downloadReleasePage(api_url, page + 1);
} else { } else {
run(); run();
} }
}); });
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) // QNetworkReply::errorOccurred added in 5.15 connect(download.get(), &Net::Download::failed, this, &PrismUpdaterApp::downloadError);
connect(rep, &QNetworkReply::errorOccurred, this, &PrismUpdaterApp::downloadError);
#else
connect(rep, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), this, &WindowsUpdaterApp::downloadError); m_current_task.reset(download);
#endif connect(download.get(), &Net::Download::finished, this, [this](){
connect(rep, &QNetworkReply::sslErrors, this, &PrismUpdaterApp::sslErrors); qDebug() << "Download" << m_current_task->getUid().toString() << "finsihed";
connect(rep, &QNetworkReply::readyRead, this, [this, responce]() { m_current_task.reset();
auto data = m_reply->readAll(); m_current_url = "";
responce->append(data);
}); });
QCoreApplication::processEvents();
QMetaObject::invokeMethod(download.get(), &Task::start, Qt::QueuedConnection);
} }
int PrismUpdaterApp::parseReleasePage(const QByteArray* responce) int PrismUpdaterApp::parseReleasePage(const QByteArray* responce)
@ -624,24 +640,7 @@ bool PrismUpdaterApp::needUpdate(const GitHubRelease& release)
return current_ver < release.version; return current_ver < release.version;
} }
void PrismUpdaterApp::downloadError(QNetworkReply::NetworkError error) void PrismUpdaterApp::downloadError(QString reason)
{ {
if (error == QNetworkReply::OperationCanceledError) { fail(QString("Network request Failed: %1 with reason %2").arg(m_current_url).arg(reason));
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<QSslError>& 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);
} }

View File

@ -36,6 +36,10 @@
#include <QUrl> #include <QUrl>
#include <memory> #include <memory>
#include "QObjectPtr.h"
#include "net/Download.h"
#define PRISM_EXTERNAL_EXE #define PRISM_EXTERNAL_EXE
#include "FileSystem.h" #include "FileSystem.h"
@ -69,8 +73,10 @@ class PrismUpdaterApp : public QApplication {
QList<GitHubRelease> newerReleases(); QList<GitHubRelease> newerReleases();
QList<GitHubRelease> nonDraftReleases(); QList<GitHubRelease> nonDraftReleases();
void downloadError(QNetworkReply::NetworkError error); public slots:
void sslErrors(const QList<QSslError>& errors); void downloadError(QString reason);
private:
const QString& root() { return m_rootPath; } const QString& root() { return m_rootPath; }
@ -95,8 +101,9 @@ class PrismUpdaterApp : public QApplication {
QString m_prismGitCommit; QString m_prismGitCommit;
Status m_status = Status::Starting; Status m_status = Status::Starting;
QNetworkAccessManager* m_network; shared_qobject_ptr<QNetworkAccessManager> m_network;
QNetworkReply* m_reply; QString m_current_url;
Task::Ptr m_current_task;
QList<GitHubRelease> m_releases; QList<GitHubRelease> m_releases;
public: public: