diff options
| author | Salanto <62221668+Salanto@users.noreply.github.com> | 2022-06-06 10:14:44 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-06-06 19:14:44 +0200 |
| commit | f0a5e48f5ca6834c0f24b167c904a030894f706e (patch) | |
| tree | 0e7ae1497d0164e3a1a3c1d61a88e4f719beb5b5 /src/networkmanager.cpp | |
| parent | c4f459b6cce6382cbd7c1960a6738a5a8a45ab8c (diff) | |
Dual-Stack AO2 Client to handle both TCP and Websocket connections seemlessly (#696)
* Replace TCP Serversocket with Websocket
* Have TCP sockets live harmoniously with WS
"like 5 lines" yeah probably lost a bet.
* Update .gitlab-ci.yml
* hack to fix favorites
* Add support for websockets in the favorites list (serverlist.txt)
Make "add_favorite_server" remember the socket type
* Preserve old serverlist style
This will keep new entries compatible with 2.9 and prior clients. Makes parsing the list easier too.
* Add lookup table and correct write code to use lowercase
* I have no idea what a lookup table is, but this looks close enough
* Fix lookup table
* Otherwise backend selection behaviour is inverted
* clang-tidy had one job
* Yet it did not do it.
Co-authored-by: oldmud0 <oldmud0@users.noreply.github.com>
* const p_data
* Switch serverlist.txt to an ini format
* Fixes an Omni bug where : would split the servername
* Utilises internally QSettings properly for low parsing effort and clear structure
* Automatically migrates the legacy serverlist.txt to favorite_servers.ini
* Pleases my OCD
* Replace sample serverlist.
Co-authored-by: oldmud0 <oldmud0@users.noreply.github.com>
Co-authored-by: stonedDiscord <Tukz@gmx.de>
Co-authored-by: Alex Noir <Varsash@gmail.com>
Diffstat (limited to 'src/networkmanager.cpp')
| -rw-r--r-- | src/networkmanager.cpp | 108 |
1 files changed, 92 insertions, 16 deletions
diff --git a/src/networkmanager.cpp b/src/networkmanager.cpp index 4c823852..8f419fce 100644 --- a/src/networkmanager.cpp +++ b/src/networkmanager.cpp @@ -4,6 +4,7 @@ #include "debug_functions.h" #include "lobby.h" +#include <QAbstractSocket> #include <QJsonArray> #include <QJsonDocument> #include <QNetworkReply> @@ -12,15 +13,9 @@ NetworkManager::NetworkManager(AOApplication *parent) : QObject(parent) { ao_app = parent; - server_socket = new QTcpSocket(this); http = new QNetworkAccessManager(this); heartbeat_timer = new QTimer(this); - connect(server_socket, &QTcpSocket::readyRead, this, - &NetworkManager::handle_server_packet); - connect(server_socket, &QTcpSocket::disconnected, ao_app, - &AOApplication::server_disconnected); - QString master_config = ao_app->configini->value("master", "").value<QString>(); if (!master_config.isEmpty() && QUrl(master_config).scheme().startsWith("http")) { @@ -60,10 +55,18 @@ void NetworkManager::ms_request_finished(QNetworkReply *reply, const auto entry = entryRef.toObject(); server_type server; server.ip = entry["ip"].toString(); - server.port = entry["port"].toInt(); server.name = entry["name"].toString(); server.desc = entry["description"].toString(tr("No description provided.")); - server_list.append(server); + if (entry["ws_port"].isDouble()) { + server.socket_type = WEBSOCKETS; + server.port = entry["ws_port"].toInt(); + } else { + server.socket_type = TCP; + server.port = entry["port"].toInt(); + } + if (server.port != 0) { + server_list.append(server); + } } ao_app->set_server_list(server_list); @@ -128,26 +131,99 @@ void NetworkManager::request_document(MSDocumentType document_type, void NetworkManager::connect_to_server(server_type p_server) { - server_socket->close(); - server_socket->abort(); + disconnect_from_server(); qInfo().nospace().noquote() << "connecting to " << p_server.ip << ":" << p_server.port; - server_socket->connectToHost(p_server.ip, p_server.port); + switch (p_server.socket_type) { + default: + p_server.socket_type = TCP; + [[fallthrough]]; + case TCP: + qInfo() << "using TCP backend"; + server_socket.tcp = new QTcpSocket(this); + + connect(server_socket.tcp, &QAbstractSocket::connected, this, [] { + qDebug() << "established connection to server"; + }); + connect(server_socket.tcp, &QIODevice::readyRead, this, [this] { + handle_server_packet(QString::fromUtf8(server_socket.tcp->readAll())); + }); + connect(server_socket.tcp, &QAbstractSocket::disconnected, ao_app, + &AOApplication::server_disconnected); + connect(server_socket.tcp, &QAbstractSocket::errorOccurred, this, [this] { + qCritical() << "TCP socket error:" << server_socket.tcp->errorString(); + }); + + server_socket.tcp->connectToHost(p_server.ip, p_server.port); + break; + case WEBSOCKETS: + qInfo() << "using WebSockets backend"; + server_socket.ws = new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this); + + connect(server_socket.ws, &QWebSocket::connected, this, [] { + qDebug() << "established connection to server"; + }); + connect(server_socket.ws, &QWebSocket::textMessageReceived, this, + &NetworkManager::handle_server_packet); + connect(server_socket.ws, &QWebSocket::disconnected, ao_app, + &AOApplication::server_disconnected); + connect(server_socket.ws, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error), + this, [this] { + qCritical() << "WebSockets error:" << server_socket.ws->errorString(); + }); + + QUrl url; + url.setScheme("ws"); + url.setHost(p_server.ip); + url.setPort(p_server.port); + QNetworkRequest req(url); + req.setHeader(QNetworkRequest::UserAgentHeader, get_user_agent()); + server_socket.ws->open(req); + break; + } + + connected = true; + active_connection_type = p_server.socket_type; +} + +void NetworkManager::disconnect_from_server() +{ + if (!connected) + return; + + switch (active_connection_type) { + case TCP: + server_socket.tcp->close(); + server_socket.tcp->deleteLater(); + break; + case WEBSOCKETS: + server_socket.ws->close(QWebSocketProtocol::CloseCodeGoingAway); + server_socket.ws->deleteLater(); + break; + } + + connected = false; } void NetworkManager::ship_server_packet(QString p_packet) { - server_socket->write(p_packet.toUtf8()); + switch (active_connection_type) { + case TCP: + server_socket.tcp->write(p_packet.toUtf8()); + break; + case WEBSOCKETS: + server_socket.ws->sendTextMessage(p_packet); + break; + } } -void NetworkManager::handle_server_packet() +void NetworkManager::handle_server_packet(const QString& p_data) { - QByteArray buffer = server_socket->readAll(); - QString in_data = QString::fromUtf8(buffer, buffer.size()); + QString in_data = p_data; - if (!in_data.endsWith("%")) { + if (!p_data.endsWith("%")) { partial_packet = true; temp_packet += in_data; return; |
