curl: add verbose logging

and really verbose logging i you use --verbose-curl
This commit is contained in:
Megamouse 2021-11-10 23:34:39 +01:00
parent b736691bde
commit 2359ba9aed
5 changed files with 94 additions and 27 deletions

View File

@ -226,22 +226,23 @@ struct fatal_error_listener final : logs::listener
}
};
constexpr auto arg_headless = "headless";
constexpr auto arg_no_gui = "no-gui";
constexpr auto arg_high_dpi = "hidpi";
constexpr auto arg_rounding = "dpi-rounding";
constexpr auto arg_styles = "styles";
constexpr auto arg_style = "style";
constexpr auto arg_stylesheet = "stylesheet";
constexpr auto arg_config = "config";
constexpr auto arg_q_debug = "qDebug";
constexpr auto arg_error = "error";
constexpr auto arg_updating = "updating";
constexpr auto arg_user_id = "user-id";
constexpr auto arg_installfw = "installfw";
constexpr auto arg_installpkg = "installpkg";
constexpr auto arg_commit_db = "get-commit-db";
constexpr auto arg_timer = "high-res-timer";
constexpr auto arg_headless = "headless";
constexpr auto arg_no_gui = "no-gui";
constexpr auto arg_high_dpi = "hidpi";
constexpr auto arg_rounding = "dpi-rounding";
constexpr auto arg_styles = "styles";
constexpr auto arg_style = "style";
constexpr auto arg_stylesheet = "stylesheet";
constexpr auto arg_config = "config";
constexpr auto arg_q_debug = "qDebug";
constexpr auto arg_error = "error";
constexpr auto arg_updating = "updating";
constexpr auto arg_user_id = "user-id";
constexpr auto arg_installfw = "installfw";
constexpr auto arg_installpkg = "installpkg";
constexpr auto arg_commit_db = "get-commit-db";
constexpr auto arg_timer = "high-res-timer";
constexpr auto arg_verbose_curl = "verbose-curl";
int find_arg(std::string arg, int& argc, char* argv[])
{
@ -536,12 +537,17 @@ int main(int argc, char** argv)
parser.addOption(QCommandLineOption(arg_updating, "For internal usage."));
parser.addOption(QCommandLineOption(arg_commit_db, "Update commits.lst cache. Optional arguments: <path> <sha>"));
parser.addOption(QCommandLineOption(arg_timer, "Enable high resolution timer for better performance (windows)", "enabled", "1"));
parser.addOption(QCommandLineOption(arg_verbose_curl, "Enable verbose curl logging."));
parser.process(app->arguments());
// Don't start up the full rpcs3 gui if we just want the version or help.
if (parser.isSet(version_option) || parser.isSet(help_option))
return 0;
// Set curl to verbose if needed
rpcs3::curl::s_curl_verbose = parser.isSet(arg_verbose_curl);
// Handle update of commit database
if (parser.isSet(arg_commit_db))
{
#ifdef _WIN32
@ -619,7 +625,7 @@ int main(int argc, char** argv)
QByteArray buf;
// CURL handle to work with GitHub API
curl_handle curl;
rpcs3::curl::curl_handle curl;
struct curl_slist* hhdr{};
hhdr = curl_slist_append(hhdr, "Accept: application/vnd.github.v3+json");
@ -657,10 +663,14 @@ int main(int argc, char** argv)
break;
}
// Reset error buffer before we call curl_easy_perform
curl.reset_error_buffer();
err = curl_easy_perform(curl);
if (err != CURLE_OK)
{
fprintf(stderr, "Curl error:\n%s", curl_easy_strerror(err));
const std::string error_string = curl.get_verbose_error(err);
fprintf(stderr, "curl_easy_perform(): %s", error_string.c_str());
break;
}

View File

@ -8,16 +8,29 @@
LOG_CHANNEL(network_log, "NET");
namespace rpcs3::curl
{
curl_handle::curl_handle(QObject* parent) : QObject(parent)
{
reset_error_buffer();
m_curl = curl_easy_init();
CURLcode err = curl_easy_setopt(m_curl, CURLOPT_ERRORBUFFER, m_error_buffer.data());
if (err != CURLE_OK) network_log.error("curl_easy_setopt(CURLOPT_ERRORBUFFER): %s", curl_easy_strerror(err));
m_uses_error_buffer = err == CURLE_OK;
err = curl_easy_setopt(m_curl, CURLOPT_VERBOSE, s_curl_verbose);
if (err != CURLE_OK) network_log.error("curl_easy_setopt(CURLOPT_VERBOSE, %d): %s", s_curl_verbose, curl_easy_strerror(err));
#ifdef _WIN32
// This shouldn't be needed on linux
const std::string path_to_cert = rpcs3::utils::get_exe_dir() + "cacert.pem";
const std::string ansi_path = utf8_path_to_ansi_path(path_to_cert);
const CURLcode err = curl_easy_setopt(m_curl, CURLOPT_CAINFO, ansi_path.data());
err = curl_easy_setopt(m_curl, CURLOPT_CAINFO, ansi_path.data());
if (err != CURLE_OK) network_log.error("curl_easy_setopt(CURLOPT_CAINFO, %s) error: %s", ansi_path, curl_easy_strerror(err));
#endif
}
@ -31,3 +44,25 @@ CURL* curl_handle::get_curl() const
{
return m_curl;
}
void curl_handle::reset_error_buffer()
{
ensure(m_error_buffer.size() == CURL_ERROR_SIZE);
m_error_buffer[0] = 0;
}
std::string curl_handle::get_verbose_error(CURLcode code)
{
if (m_uses_error_buffer)
{
ensure(m_error_buffer.size() == CURL_ERROR_SIZE);
if (m_error_buffer[0])
{
return fmt::format("Curl error (%d): %s\nDetails: %s", static_cast<int>(code), curl_easy_strerror(code), m_error_buffer.data());
}
}
return fmt::format("Curl error (%d): %s", static_cast<int>(code), curl_easy_strerror(code));
}
}

View File

@ -1,5 +1,6 @@
#pragma once
#include <array>
#include <QObject>
#ifndef CURL_STATICLIB
@ -7,11 +8,12 @@
#endif
#include <curl/curl.h>
namespace rpcs3::curl
{
static bool s_curl_verbose = false;
class curl_handle : public QObject
{
private:
CURL* m_curl = nullptr;
public:
explicit curl_handle(QObject* parent = nullptr);
~curl_handle();
@ -22,4 +24,14 @@ public:
{
return get_curl();
}
void reset_error_buffer();
std::string get_verbose_error(CURLcode code);
private:
CURL* m_curl = nullptr;
bool m_uses_error_buffer = false;
std::array<char, CURL_ERROR_SIZE> m_error_buffer;
};
}

View File

@ -19,7 +19,7 @@ usz curl_write_cb_compat(char* ptr, usz /*size*/, usz nmemb, void* userdata)
downloader::downloader(QWidget* parent)
: QObject(parent)
, m_parent(parent)
, m_curl(new curl_handle(this))
, m_curl(new rpcs3::curl::curl_handle(this))
{
}
@ -64,12 +64,15 @@ void downloader::start(const std::string& url, bool follow_location, bool show_p
m_thread = QThread::create([this]
{
const auto result = curl_easy_perform(m_curl->get_curl());
// Reset error buffer before we call curl_easy_perform
m_curl->reset_error_buffer();
const CURLcode result = curl_easy_perform(m_curl->get_curl());
m_curl_success = result == CURLE_OK;
if (!m_curl_success && !m_curl_abort)
{
const std::string error = "Curl error: " + std::string{ curl_easy_strerror(result) };
const std::string error = fmt::format("curl_easy_perform(): %s", m_curl->get_verbose_error(result));
network_log.error("%s", error);
Q_EMIT signal_download_error(QString::fromStdString(error));
}

View File

@ -3,7 +3,14 @@
#include <QObject>
#include "util/atomic.hpp"
class curl_handle;
namespace rpcs3
{
namespace curl
{
class curl_handle;
}
}
class progress_dialog;
class downloader : public QObject
@ -35,7 +42,7 @@ Q_SIGNALS:
private:
QWidget* m_parent = nullptr;
curl_handle* m_curl = nullptr;
rpcs3::curl::curl_handle* m_curl = nullptr;
QByteArray m_curl_buf;
atomic_t<bool> m_curl_abort = false;
atomic_t<bool> m_curl_success = false;