diff --git a/rpcs3/rpcs3qt/downloader.cpp b/rpcs3/rpcs3qt/downloader.cpp index ae97dc8f77..39078c880d 100644 --- a/rpcs3/rpcs3qt/downloader.cpp +++ b/rpcs3/rpcs3qt/downloader.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "downloader.h" #include "curl_handle.h" @@ -7,6 +8,8 @@ #include "util/logs.hpp" +#include + LOG_CHANNEL(network_log, "NET"); usz curl_write_cb_compat(char* ptr, usz /*size*/, usz nmemb, void* userdata) @@ -31,7 +34,7 @@ downloader::~downloader() } } -void downloader::start(const std::string& url, bool follow_location, bool show_progress_dialog, const QString& progress_dialog_title, bool keep_progress_dialog_open, int expected_size) +void downloader::start(const std::string& url, bool follow_location, bool show_progress_dialog, const QString& progress_dialog_title, bool keep_progress_dialog_open, int expected_size, bool check_return_code, bool again) { network_log.notice("Starting download from URL: %s", url); @@ -49,6 +52,21 @@ void downloader::start(const std::string& url, bool follow_location, bool show_p m_curl_buf.clear(); m_curl_abort = false; + if (again) + { + m_download_attempts++; + + if (m_progress_dialog && m_download_attempts > 1) + { + handle_buffer_update(0, 100); + m_progress_dialog->setLabelText(tr("Please wait... Trying again")); + } + } + else + { + m_download_attempts = 1; + } + CURLcode err = curl_easy_setopt(m_curl->get_curl(), CURLOPT_URL, url.c_str()); if (err != CURLE_OK) network_log.error("curl_easy_setopt(CURLOPT_URL, %s) error: %s", url, curl_easy_strerror(err)); @@ -77,7 +95,7 @@ void downloader::start(const std::string& url, bool follow_location, bool show_p } }); - connect(m_thread, &QThread::finished, this, [this]() + connect(m_thread, &QThread::finished, this, [=, this]() { if (m_curl_abort) { @@ -93,6 +111,21 @@ void downloader::start(const std::string& url, bool follow_location, bool show_p if (m_curl_success) { network_log.notice("Download finished"); + + if (check_return_code && m_download_attempts < 3) + { + const QJsonObject json_data = QJsonDocument::fromJson(m_curl_buf).object(); + const int return_code = json_data["return_code"].toInt(-255); + + if (return_code == -255) + { + network_log.error("Error during download. Trying to download again (attempts=%d, return_code=%d)", m_download_attempts, return_code); + std::this_thread::sleep_for(500ms); // Wait for a little while + start(url, follow_location, show_progress_dialog, progress_dialog_title, keep_progress_dialog_open, expected_size, check_return_code, true); + return; + } + } + Q_EMIT signal_download_finished(m_curl_buf); } }); diff --git a/rpcs3/rpcs3qt/downloader.h b/rpcs3/rpcs3qt/downloader.h index 5a2a44fabe..be0cd0e568 100644 --- a/rpcs3/rpcs3qt/downloader.h +++ b/rpcs3/rpcs3qt/downloader.h @@ -21,7 +21,7 @@ public: explicit downloader(QWidget* parent = nullptr); ~downloader(); - void start(const std::string& url, bool follow_location, bool show_progress_dialog, const QString& progress_dialog_title = "", bool keep_progress_dialog_open = false, int expected_size = -1); + void start(const std::string& url, bool follow_location, bool show_progress_dialog, const QString& progress_dialog_title = "", bool keep_progress_dialog_open = false, int expected_size = -1, bool check_return_code = true, bool again = false); usz update_buffer(char* data, usz size); void update_progress_dialog(const QString& title) const; @@ -46,6 +46,7 @@ private: atomic_t m_curl_abort = false; atomic_t m_curl_success = false; double m_actual_download_size = -1.0; + u32 m_download_attempts = 0; progress_dialog* m_progress_dialog = nullptr; atomic_t m_keep_progress_dialog_open = false; diff --git a/rpcs3/rpcs3qt/game_compatibility.cpp b/rpcs3/rpcs3qt/game_compatibility.cpp index 2845659716..b9cb32a7c1 100644 --- a/rpcs3/rpcs3qt/game_compatibility.cpp +++ b/rpcs3/rpcs3qt/game_compatibility.cpp @@ -69,7 +69,7 @@ void game_compatibility::handle_download_canceled() bool game_compatibility::ReadJSON(const QJsonObject& json_data, bool after_download) { - const int return_code = json_data["return_code"].toInt(); + const int return_code = json_data["return_code"].toInt(-255); if (return_code < 0) { @@ -78,15 +78,10 @@ bool game_compatibility::ReadJSON(const QJsonObject& json_data, bool after_downl std::string error_message; switch (return_code) { - case -1: - error_message = "Server Error - Internal Error"; - break; - case -2: - error_message = "Server Error - Maintenance Mode"; - break; - default: - error_message = "Server Error - Unknown Error"; - break; + case -1: error_message = "Server Error - Internal Error"; break; + case -2: error_message = "Server Error - Maintenance Mode"; break; + case -255: error_message = "Server Error - Return code not found"; break; + default: error_message = "Server Error - Unknown Error"; break; } compat_log.error("%s: return code %d", error_message, return_code); Q_EMIT DownloadError(QString::fromStdString(error_message) + " " + QString::number(return_code)); diff --git a/rpcs3/rpcs3qt/patch_manager_dialog.cpp b/rpcs3/rpcs3qt/patch_manager_dialog.cpp index 227a4a3a47..a41d8ed7b5 100644 --- a/rpcs3/rpcs3qt/patch_manager_dialog.cpp +++ b/rpcs3/rpcs3qt/patch_manager_dialog.cpp @@ -1184,9 +1184,9 @@ bool patch_manager_dialog::handle_json(const QByteArray& data) } if (return_code != -1) - patch_log.error("Patch download error: %s return code: %d", error_message, return_code); + patch_log.error("Patch download error: %s, return code: %d", error_message, return_code); else - patch_log.warning("Patch download error: %s return code: %d", error_message, return_code); + patch_log.warning("Patch download error: %s, return code: %d", error_message, return_code); return false; } diff --git a/rpcs3/rpcs3qt/update_manager.cpp b/rpcs3/rpcs3qt/update_manager.cpp index 6929e08318..ec4d7ce44f 100644 --- a/rpcs3/rpcs3qt/update_manager.cpp +++ b/rpcs3/rpcs3qt/update_manager.cpp @@ -135,9 +135,9 @@ bool update_manager::handle_json(bool automatic, bool check_only, bool auto_acce } if (return_code != -1) - update_log.error("Update error: %s return code: %d", error_message, return_code); + update_log.error("Update error: %s, return code: %d", error_message, return_code); else - update_log.warning("Update error: %s return code: %d", error_message, return_code); + update_log.warning("Update error: %s, return code: %d", error_message, return_code); // If a user clicks "Check for Updates" with a custom build ask him if he's sure he wants to update to latest version if (!automatic && return_code == -1) diff --git a/rpcs3/rpcs3qt/update_manager.h b/rpcs3/rpcs3qt/update_manager.h index 8e7d9e8eb0..98ef5cf3f1 100644 --- a/rpcs3/rpcs3qt/update_manager.h +++ b/rpcs3/rpcs3qt/update_manager.h @@ -13,6 +13,14 @@ class update_manager final : public QObject { Q_OBJECT +public: + update_manager(QObject* parent, std::shared_ptr gui_settings); + void check_for_updates(bool automatic, bool check_only, bool auto_accept, QWidget* parent = nullptr); + void update(bool auto_accept); + +Q_SIGNALS: + void signal_update_available(bool update_available); + private: downloader* m_downloader = nullptr; QWidget* m_parent = nullptr; @@ -45,12 +53,4 @@ private: bool handle_json(bool automatic, bool check_only, bool auto_accept, const QByteArray& data); bool handle_rpcs3(const QByteArray& data, bool auto_accept); - -public: - update_manager(QObject* parent, std::shared_ptr gui_settings); - void check_for_updates(bool automatic, bool check_only, bool auto_accept, QWidget* parent = nullptr); - void update(bool auto_accept); - -Q_SIGNALS: - void signal_update_available(bool update_available); };