From 79c2262cae02b513aee70943f7e07a9205316bdf Mon Sep 17 00:00:00 2001 From: Osmium Sorcerer Date: Sun, 22 Mar 2026 17:57:13 +0000 Subject: Support Secure WebSocket Add full WSS support to public server list (using wss_port, overriding insecure port), favorite servers list, and direct connections, and show which servers are secure. Revert the upstream's removal of `legacy` ServerInfo field, as I use it to filter out legacy servers. To differentiate schemes, the `scheme` field is used, either "ws" or "wss". I don't see the reason to add "tcp" protocol when we don't even support it. For the UI, add icons for secure and insecure connections. Highlight secure servers with a green background. In the favorite server dialog, a checkbox was added to select whether the server is using WSS. In the direct connection dialog, support "wss" scheme and default ports: 80 for WS, 443 for WSS, as per the WebSocket specification. --- data.qrc | 2 ++ data/icons/https.svg | 1 + data/icons/noencryption.svg | 1 + data/ui/favorite_server_dialog.ui | 13 +++++++++++- src/lobby.cpp | 39 +++++++++++++++++++++++++---------- src/network/serverinfo.h | 3 ++- src/network/websocketconnection.cpp | 2 +- src/networkmanager.cpp | 6 +++--- src/options.cpp | 18 +++++++--------- src/widgets/direct_connect_dialog.cpp | 15 +++++++------- src/widgets/server_editor_dialog.cpp | 3 +++ src/widgets/server_editor_dialog.h | 2 ++ 12 files changed, 70 insertions(+), 35 deletions(-) create mode 100644 data/icons/https.svg create mode 100644 data/icons/noencryption.svg diff --git a/data.qrc b/data.qrc index d44218a5..bad64a50 100644 --- a/data.qrc +++ b/data.qrc @@ -16,5 +16,7 @@ data/ui/lobby_assets/down-arrow.png data/ui/lobby_assets/up-arrow.png data/ui/moderator_action_dialog.ui + data/icons/https.svg + data/icons/noencryption.svg diff --git a/data/icons/https.svg b/data/icons/https.svg new file mode 100644 index 00000000..87a3c2b9 --- /dev/null +++ b/data/icons/https.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/data/icons/noencryption.svg b/data/icons/noencryption.svg new file mode 100644 index 00000000..91524c5f --- /dev/null +++ b/data/icons/noencryption.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/data/ui/favorite_server_dialog.ui b/data/ui/favorite_server_dialog.ui index b90514dc..1fda9229 100644 --- a/data/ui/favorite_server_dialog.ui +++ b/data/ui/favorite_server_dialog.ui @@ -78,13 +78,24 @@ + + + Secure: + + + + + + + + Description: - + diff --git a/src/lobby.cpp b/src/lobby.cpp index 424f634b..29101c6f 100644 --- a/src/lobby.cpp +++ b/src/lobby.cpp @@ -471,19 +471,21 @@ void Lobby::list_servers() QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_serverlist_tree); treeItem->setData(0, Qt::DisplayRole, i); - if (i_server.protocol == "tcp") + QIcon insecureIcon(":/data/icons/noencryption.svg"); + QIcon secureIcon(":/data/icons/https.svg"); + QColor secureColor(80, 120, 80); + treeItem->setText(1, i_server.name); + if (i_server.scheme == "wss") { - treeItem->setText(1, "(Legacy) " + i_server.name); - treeItem->setBackground(0, Qt::darkRed); - treeItem->setBackground(1, Qt::darkRed); - - QString tooltip = tr("Unable to connect to server. Server is missing WebSocket support."); - treeItem->setToolTip(0, tooltip); - treeItem->setToolTip(1, tooltip); + treeItem->setIcon(1, secureIcon); + treeItem->setToolTip(1, "Connection is secure."); + treeItem->setBackground(0, secureColor); + treeItem->setBackground(1, secureColor); } - else + else if (i_server.scheme == "ws") { - treeItem->setText(1, i_server.name); + treeItem->setIcon(1, insecureIcon); + treeItem->setToolTip(1, "Insecure. Traffic can be intercepted or modified."); } i++; @@ -504,7 +506,7 @@ void Lobby::list_favorites() QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_favorites_tree); treeItem->setData(0, Qt::DisplayRole, i); - if (i_server.protocol == "tcp") + if (i_server.legacy) { treeItem->setText(1, "(Legacy) " + i_server.name); treeItem->setBackground(0, Qt::darkRed); @@ -516,7 +518,22 @@ void Lobby::list_favorites() } else { + QIcon insecureIcon(":/data/icons/noencryption.svg"); + QIcon secureIcon(":/data/icons/https.svg"); + QColor secureColor(80, 120, 80); treeItem->setText(1, i_server.name); + if (i_server.scheme == "wss") + { + treeItem->setIcon(1, secureIcon); + treeItem->setToolTip(1, "Connection is secure."); + treeItem->setBackground(0, secureColor); + treeItem->setBackground(1, secureColor); + } + else if (i_server.scheme == "ws") + { + treeItem->setIcon(1, insecureIcon); + treeItem->setToolTip(1, "Insecure. Traffic can be intercepted or modified."); + } } i++; diff --git a/src/network/serverinfo.h b/src/network/serverinfo.h index de91a011..b7e00697 100644 --- a/src/network/serverinfo.h +++ b/src/network/serverinfo.h @@ -9,7 +9,8 @@ public: QString description; QString address; quint16 port = 0; - QString protocol = "ws"; + bool legacy = false; + QString scheme = "ws"; QString toString() const; }; diff --git a/src/network/websocketconnection.cpp b/src/network/websocketconnection.cpp index e9cc1ef9..d51cdcaf 100644 --- a/src/network/websocketconnection.cpp +++ b/src/network/websocketconnection.cpp @@ -32,7 +32,7 @@ void WebSocketConnection::connectToServer(const ServerInfo &server) disconnectFromServer(); QUrl url; - url.setScheme(server.protocol); + url.setScheme(server.scheme); url.setHost(server.address); url.setPort(server.port); diff --git a/src/networkmanager.cpp b/src/networkmanager.cpp index 02d5961e..a7bb54ef 100644 --- a/src/networkmanager.cpp +++ b/src/networkmanager.cpp @@ -63,17 +63,17 @@ void NetworkManager::ms_request_finished(QNetworkReply *reply) if (entry.contains("wss_port")) { server.port = entry["wss_port"].toInt(); - server.protocol = "wss"; + server.scheme = "wss"; } else if (entry.contains("ws_port")) { server.port = entry["ws_port"].toInt(); - server.protocol = "ws"; + server.scheme = "ws"; } else { server.port = entry["port"].toInt(); - server.protocol = "tcp"; + server.legacy = true; } if (server.port != 0) diff --git a/src/options.cpp b/src/options.cpp index d25eea09..3d400c25 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -678,14 +678,7 @@ QVector Options::favorites() f_server.port = favorite.value("port", 27016).toInt(); f_server.name = favorite.value("name", "Missing Name").toString(); f_server.description = favorite.value("desc", "No description").toString(); - if (favorite.contains("protocol")) - { - f_server.protocol = favorite.value("protocol").toString(); - } - else - { - f_server.protocol = "tcp"; - } + f_server.scheme = favorite.value("scheme", "ws").toString(); serverlist.append(std::move(f_server)); favorite.endGroup(); @@ -705,7 +698,8 @@ void Options::setFavorites(QVector value) favorite.setValue("address", fav_server.address); favorite.setValue("port", fav_server.port); favorite.setValue("desc", fav_server.description); - favorite.setValue("protocol", fav_server.protocol); + favorite.setValue("legacy", fav_server.legacy); + favorite.setValue("scheme", fav_server.scheme); favorite.endGroup(); } favorite.sync(); @@ -726,7 +720,8 @@ void Options::addFavorite(ServerInfo server) favorite.setValue("address", server.address); favorite.setValue("port", server.port); favorite.setValue("desc", server.description); - favorite.setValue("protocol", server.protocol); + favorite.setValue("legacy", server.legacy); + favorite.setValue("scheme", server.scheme); favorite.endGroup(); favorite.sync(); } @@ -738,7 +733,8 @@ void Options::updateFavorite(ServerInfo server, int index) favorite.setValue("address", server.address); favorite.setValue("port", server.port); favorite.setValue("desc", server.description); - favorite.setValue("protocol", server.protocol); + favorite.setValue("legacy", server.legacy); + favorite.setValue("scheme", server.scheme); favorite.endGroup(); favorite.sync(); } diff --git a/src/widgets/direct_connect_dialog.cpp b/src/widgets/direct_connect_dialog.cpp index f8c77b85..9859889d 100644 --- a/src/widgets/direct_connect_dialog.cpp +++ b/src/widgets/direct_connect_dialog.cpp @@ -51,7 +51,7 @@ void DirectConnectDialog::onConnectPressed() QString l_hostname = ui_direct_hostname_edit->text(); if (!SCHEME_PATTERN.match(l_hostname).hasMatch()) { - l_hostname = "ws://" % l_hostname; + l_hostname = "wss://" % l_hostname; } QUrl l_url(l_hostname); @@ -61,20 +61,21 @@ void DirectConnectDialog::onConnectPressed() return; } - if (l_url.scheme() != "ws") + if (l_url.scheme() != "ws" && l_url.scheme() != "wss") { - call_error(tr("Invalid URL scheme. Only ws:// is supported.")); + call_error(tr("Invalid URL scheme. Only ws: and wss: are supported.")); return; } - if (l_url.port() == -1) + int port = l_url.port(); + if (port == -1) { - call_error(tr("Invalid server port.")); - return; + port = (l_url.scheme() == "wss") ? 443 : 80; } ServerInfo l_server; l_server.address = l_url.host(); - l_server.port = l_url.port(); + l_server.port = port; + l_server.scheme = l_url.scheme(); l_server.name = "Direct Connection"; net_manager->connect_to_server(l_server); diff --git a/src/widgets/server_editor_dialog.cpp b/src/widgets/server_editor_dialog.cpp index 03c8d6c6..8f987f6a 100644 --- a/src/widgets/server_editor_dialog.cpp +++ b/src/widgets/server_editor_dialog.cpp @@ -31,6 +31,7 @@ ServerEditorDialog::ServerEditorDialog(QWidget *parent) FROM_UI(QLineEdit, name); FROM_UI(QLineEdit, hostname); FROM_UI(QSpinBox, port); + FROM_UI(QCheckBox, secure_cb); FROM_UI(QPlainTextEdit, description); FROM_UI(QDialogButtonBox, button_box); @@ -49,6 +50,7 @@ ServerEditorDialog::ServerEditorDialog(const ServerInfo &server, QWidget *parent ui_name->setText(server.name); ui_hostname->setText(server.address); ui_port->setValue(server.port); + ui_secure_cb->setChecked(server.scheme == "wss"); ui_description->setPlainText(server.description); } @@ -58,6 +60,7 @@ ServerInfo ServerEditorDialog::currentServerInfo() const server.name = ui_name->text(); server.address = ui_hostname->text(); server.port = ui_port->value(); + server.scheme = ui_secure_cb->isChecked() ? "wss" : "ws"; server.description = ui_description->toPlainText(); return server; } diff --git a/src/widgets/server_editor_dialog.h b/src/widgets/server_editor_dialog.h index a8844d4b..7b0bb651 100644 --- a/src/widgets/server_editor_dialog.h +++ b/src/widgets/server_editor_dialog.h @@ -2,6 +2,7 @@ #include "network/serverinfo.h" +#include #include #include #include @@ -29,6 +30,7 @@ private: QLineEdit *ui_name; QLineEdit *ui_hostname; QSpinBox *ui_port; + QCheckBox *ui_secure_cb; QPlainTextEdit *ui_description; QDialogButtonBox *ui_button_box; -- cgit