From 9af9660c8241d7a5eb2f25778f1d00dac05a111a Mon Sep 17 00:00:00 2001 From: Sander Speetjens Date: Mon, 15 Jun 2026 11:58:00 +0200 Subject: [PATCH] client - fix ssl errors when using reverse proxy in a regular application - switch over to reverse proxy by default - allow for debug host + port without ssl --- client/main.cpp | 77 ++++++++++++++++++----------------- client/web_socket_wrapper.cpp | 13 ++++++ 2 files changed, 53 insertions(+), 37 deletions(-) diff --git a/client/main.cpp b/client/main.cpp index 3fa27f5..7a0df76 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -39,18 +39,17 @@ int main(int argc, char *argv[]) .arg(Git_version::dirty ? "-dirty" : "")); parser.addHelpOption(); + QCommandLineOption debug_option(QStringList() << "debug", + QCoreApplication::translate("main", "debug unisim_cpp server host [default: localhost:9002]."), + QCoreApplication::translate("main", "host"), QLatin1String("localhost:9002")); + parser.addOption(debug_option); + QCommandLineOption host_option(QStringList() << "s" << "server", QCoreApplication::translate("main", "unisim_cpp server host [default: localhost]."), QCoreApplication::translate("main", "host"), QLatin1String("localhost")); parser.addOption(host_option); - QCommandLineOption port_option(QStringList() << "p" - << "port", - QCoreApplication::translate("main", "Port for unisim_cpp [default: 9002]."), - QCoreApplication::translate("main", "port"), QLatin1String("9002")); - parser.addOption(port_option); - QCommandLineOption default_sim_option(QStringList() << "d" << "default", QCoreApplication::translate("main", "Default sim that loads on startup."), @@ -71,40 +70,44 @@ int main(int argc, char *argv[]) .value_or(spdlog::level::off)); QUrl url; + if (parser.isSet(debug_option)) + { + url = QUrl::fromUserInput(parser.value(debug_option)); + url.setScheme("ws"); +#if defined(__linux__) + if (url.host().endsWith(".local")) + { + QProcess p; + p.start("avahi-resolve", {"-4", "--name", url.host()}); + p.waitForFinished(-1); + QString stdout = p.readAllStandardOutput(); + QString stderr = p.readAllStandardError(); + if (!stderr.isEmpty()) + { + SPDLOG_CRITICAL("Unable to resolve {}", parser.value(host_option).toStdString()); + return -1; + } + + auto ret = stdout.split(u'\t', Qt::SkipEmptyParts); + if (ret.count() < 2) + { + SPDLOG_CRITICAL("Unable to resolve {}: not enough paramteters", parser.value(host_option).toStdString()); + } + + ret[1].removeLast(); + url.setHost(ret[1]); + } +#endif + } else + { + url.setPath("/ws"); + url.setPort(443); + url.setScheme("wss"); + url.setHost(parser.value(host_option)); + } #ifdef EMSCRIPTEN emscripten::val location = emscripten::val::global("location"); url.setHost(QString::fromStdString(location["hostname"].as())); - url.setPath("/ws"); - url.setPort(443); - url.setScheme("wss"); -#else - url.setScheme("ws"); - url.setPort(parser.value(port_option).toInt()); - url.setHost(parser.value(host_option)); -#if defined(__linux__) - if (parser.value(host_option).endsWith(".local")) - { - QProcess p; - p.start("avahi-resolve", {"-4", "--name", parser.value(host_option)}); - p.waitForFinished(-1); - QString stdout = p.readAllStandardOutput(); - QString stderr = p.readAllStandardError(); - if (!stderr.isEmpty()) - { - SPDLOG_CRITICAL("Unable to resolve {}", parser.value(host_option).toStdString()); - return -1; - } - - auto ret = stdout.split(u'\t', Qt::SkipEmptyParts); - if (ret.count() < 2) - { - SPDLOG_CRITICAL("Unable to resolve {}: not enough paramteters", parser.value(host_option).toStdString()); - } - - ret[1].removeLast(); - url.setHost(ret[1]); - } -#endif #endif QString default_sim = parser.value(default_sim_option); SPDLOG_INFO("Connecting client on {}", url.toString().toStdString()); diff --git a/client/web_socket_wrapper.cpp b/client/web_socket_wrapper.cpp index b1d697a..3084d33 100644 --- a/client/web_socket_wrapper.cpp +++ b/client/web_socket_wrapper.cpp @@ -25,6 +25,7 @@ Web_socket_wrapper::Web_socket_wrapper(const QUrl &url, QObject *parent) connect(m_web_socket, &QWebSocket::errorOccurred, this, [this](QAbstractSocket::SocketError error) { LOG_ERROR(QString::fromStdString(std::string(magic_enum::enum_name(error)))); }); + connect(m_ping_timer, &QTimer::timeout, this, [=, this] { #ifdef EMSCRIPTEN if (m_web_socket->state() != QAbstractSocket::ConnectedState) @@ -53,6 +54,18 @@ Web_socket_wrapper::Web_socket_wrapper(const QUrl &url, QObject *parent) m_web_socket->close(); emit on_closed(); }); + connect(m_web_socket, &QWebSocket::sslErrors, + this, [&](const QList &errors) { + QList exeptions; + for (const auto &err : errors) { + if (err.error() == QSslError::UnableToGetLocalIssuerCertificate) + { + exeptions.append(err); + LOG_WARN(QString("Allowing ssl error: %1 from %2").arg("UnableToGetLocalIssuerCertificate").arg(!err.certificate().isNull() ? err.certificate().subjectDisplayName() : "Unknown")); + } + } + m_web_socket->ignoreSslErrors(exeptions); + }); #endif m_ping_timer->setSingleShot(true); m_pong_timer->setSingleShot(true);