From efd2571459924f40718130f7edd28a72a76b12d7 Mon Sep 17 00:00:00 2001
From: Leifa <26681464+TrickyLeifa@users.noreply.github.com>
Date: Tue, 9 Jul 2024 13:07:30 +0200
Subject: [PATCH] Remove TCP entry point (#1007)
* Remove TCP entry point
Resolve #987
* Remove TCP entry point
* Servers that do not support WebSocket will be marked as `Legacy`
* Removal of TCP connection from the master will follow later.
* Tweaked error message
---
CMakeLists.txt | 9 +-
data/ui/favorite_server_dialog.ui | 23 +---
data/ui/lobby.ui | 18 ++-
src/datatypes.h | 19 ---
src/demoserver.cpp | 128 ++++++++----------
src/demoserver.h | 10 +-
src/lobby.cpp | 39 +++++-
src/net/netconnection.cpp | 5 -
src/net/netconnection.h | 28 ----
src/net/nettcpconnection.cpp | 102 --------------
src/net/nettcpconnection.h | 31 -----
src/net/netwebsocketconnection.h | 32 -----
src/network/serverinfo.cpp | 6 +
src/network/serverinfo.h | 15 ++
.../websocketconnection.cpp} | 36 ++---
src/network/websocketconnection.h | 43 ++++++
src/networkmanager.cpp | 35 ++---
src/networkmanager.h | 4 +-
src/options.cpp | 46 +++----
src/options.h | 3 +-
src/packet_distribution.cpp | 4 +-
src/widgets/direct_connect_dialog.cpp | 12 +-
src/widgets/server_editor_dialog.cpp | 49 +++----
src/widgets/server_editor_dialog.h | 5 +-
24 files changed, 252 insertions(+), 450 deletions(-)
delete mode 100644 src/net/netconnection.cpp
delete mode 100644 src/net/netconnection.h
delete mode 100644 src/net/nettcpconnection.cpp
delete mode 100644 src/net/nettcpconnection.h
delete mode 100644 src/net/netwebsocketconnection.h
create mode 100644 src/network/serverinfo.cpp
create mode 100644 src/network/serverinfo.h
rename src/{net/netwebsocketconnection.cpp => network/websocketconnection.cpp} (55%)
create mode 100644 src/network/websocketconnection.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8488259..2e5b24e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -78,12 +78,8 @@ add_executable(Attorney_Online
src/lobby.cpp
src/lobby.h
src/main.cpp
- src/net/netconnection.cpp
- src/net/netconnection.h
- src/net/nettcpconnection.cpp
- src/net/nettcpconnection.h
- src/net/netwebsocketconnection.cpp
- src/net/netwebsocketconnection.h
+ src/network/websocketconnection.cpp
+ src/network/websocketconnection.h
src/networkmanager.cpp
src/networkmanager.h
src/options.cpp
@@ -103,6 +99,7 @@ add_executable(Attorney_Online
src/widgets/server_editor_dialog.h
data.qrc
src/screenslidetimer.h src/screenslidetimer.cpp
+ src/network/serverinfo.h src/network/serverinfo.cpp
)
set_target_properties(Attorney_Online PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")
diff --git a/data/ui/favorite_server_dialog.ui b/data/ui/favorite_server_dialog.ui
index f0f60cb..b90514d 100644
--- a/data/ui/favorite_server_dialog.ui
+++ b/data/ui/favorite_server_dialog.ui
@@ -78,34 +78,13 @@
-
-
-
- Protocol:
-
-
-
- -
-
-
-
-
- TCP
-
-
- -
-
- WEBSOCKET
-
-
-
-
- -
Description:
- -
+
-
diff --git a/data/ui/lobby.ui b/data/ui/lobby.ui
index ceb85ff..fcc364e 100644
--- a/data/ui/lobby.ui
+++ b/data/ui/lobby.ui
@@ -316,8 +316,14 @@ QScrollBar:horizontall {
-
- background-color: rgba(140, 140, 140, 255);
-color: rgb(255, 255, 255);
+ QHeaderView, QTreeView {
+background-color: rgba(140, 140, 140, 255);
+color: rgb(255, 255, 255);
+}
+
+QToolTip {
+color: black;
+}
Qt::ElideNone
@@ -330,7 +336,7 @@ color: rgb(255, 255, 255);
#
- AlignTrailing|AlignVCenter
+ AlignLeading|AlignVCenter
@@ -369,7 +375,11 @@ color: rgb(255, 255, 255);
background-color: rgba(140, 140, 140, 255);
-color: rgb(255, 255, 255);
+color: rgb(255, 255, 255);
+
+QToolTip {
+ color: black;
+};
Qt::ElideNone
diff --git a/src/datatypes.h b/src/datatypes.h
index 97fa8c7..b87744c 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -5,25 +5,6 @@
#include
-enum ServerConnectionType
-{
- TcpServerConnection,
- WebSocketServerConnection,
-};
-
-static const QMap SERVER_CONNECTION_TYPE_STRING_MAP = {{"tcp", ServerConnectionType::TcpServerConnection}, {"ws", ServerConnectionType::WebSocketServerConnection}};
-
-struct ServerInfo
-{
- QString name;
- QString description;
- QString ip;
- int port;
- ServerConnectionType socket_type;
-
- inline QString toString() { return QString("%1 (<%2>%3:%4)").arg(name, SERVER_CONNECTION_TYPE_STRING_MAP.key(socket_type), ip, QString::number(port)); }
-};
-
struct CharacterSlot
{
QString name;
diff --git a/src/demoserver.cpp b/src/demoserver.cpp
index bc7cc4b..93eaad5 100644
--- a/src/demoserver.cpp
+++ b/src/demoserver.cpp
@@ -9,8 +9,8 @@ DemoServer::DemoServer(QObject *parent)
timer->setTimerType(Qt::PreciseTimer);
timer->setSingleShot(true);
- tcp_server = new QTcpServer(this);
- connect(tcp_server, &QTcpServer::newConnection, this, &DemoServer::accept_connection);
+ server = new QWebSocketServer(tr("DemoServer"), QWebSocketServer::NonSecureMode, this);
+ connect(server, &QWebSocketServer::newConnection, this, &DemoServer::accept_connection);
connect(timer, &QTimer::timeout, this, &DemoServer::playback);
}
@@ -30,22 +30,22 @@ void DemoServer::start_server()
{
return;
}
- if (!tcp_server->listen(QHostAddress::LocalHost, 0))
+ if (!server->listen(QHostAddress::LocalHost, 0))
{
qCritical() << "Could not start demo playback server...";
- qDebug() << tcp_server->errorString();
+ qDebug() << server->errorString();
return;
}
- this->m_port = tcp_server->serverPort();
+ this->m_port = server->serverPort();
qInfo() << "Demo server started at port" << m_port;
m_server_started = true;
}
void DemoServer::destroy_connection()
{
- QTcpSocket *temp_socket = tcp_server->nextPendingConnection();
- connect(temp_socket, &QAbstractSocket::disconnected, temp_socket, &QObject::deleteLater);
- temp_socket->disconnectFromHost();
+ QWebSocket *temp_socket = server->nextPendingConnection();
+ temp_socket->close();
+ temp_socket->deleteLater();
return;
}
@@ -80,22 +80,20 @@ void DemoServer::accept_connection()
{
// Client is already connected...
qWarning() << "Multiple connections to demo server disallowed.";
- QTcpSocket *temp_socket = tcp_server->nextPendingConnection();
- connect(temp_socket, &QAbstractSocket::disconnected, temp_socket, &QObject::deleteLater);
- temp_socket->disconnectFromHost();
+ QWebSocket *temp_socket = server->nextPendingConnection();
+ temp_socket->close();
+ temp_socket->deleteLater();
return;
}
- client_sock = tcp_server->nextPendingConnection();
- connect(client_sock, &QAbstractSocket::disconnected, this, &DemoServer::client_disconnect);
- connect(client_sock, &QAbstractSocket::readyRead, this, &DemoServer::recv_data);
- client_sock->write("decryptor#NOENCRYPT#%");
+ client_sock = server->nextPendingConnection();
+ connect(client_sock, &QWebSocket::disconnected, this, &DemoServer::client_disconnect);
+ connect(client_sock, &QWebSocket::textMessageReceived, this, &DemoServer::recv_data);
+ client_sock->sendTextMessage("decryptor#NOENCRYPT#%");
}
-void DemoServer::recv_data()
+void DemoServer::recv_data(const QString &message)
{
- QString in_data = QString::fromUtf8(client_sock->readAll());
-
- const QStringList packet_list = in_data.split("%", Qt::SkipEmptyParts);
+ const QStringList packet_list = message.split("%", Qt::SkipEmptyParts);
for (const QString &packet : packet_list)
{
QStringList f_contents;
@@ -145,39 +143,35 @@ void DemoServer::handle_packet(AOPacket p_packet)
if (header == "HI")
{
- client_sock->write("ID#0#DEMOINTERNAL#0#%");
+ client_sock->sendTextMessage("ID#0#DEMOINTERNAL#0#%");
}
else if (header == "ID")
{
QStringList feature_list = {"noencryption", "yellowtext", "prezoom", "flipping", "customobjections", "fastloading", "deskmod", "evidence", "cccc_ic_support", "arup", "casing_alerts", "modcall_reason", "looping_sfx", "additive", "effects", "y_offset", "expanded_desk_mods"};
- client_sock->write("PN#0#1#%");
- client_sock->write("FL#");
- client_sock->write(feature_list.join('#').toUtf8());
- client_sock->write("#%");
+ client_sock->sendTextMessage("PN#0#1#%");
+ client_sock->sendTextMessage("FL#" + feature_list.join('#') + "#%");
}
else if (header == "askchaa")
{
- client_sock->write("SI#");
- client_sock->write(QString::number(num_chars).toUtf8());
- client_sock->write("#0#1#%");
+ client_sock->sendTextMessage("SI#" + QString::number(num_chars) + "#0#1#%");
}
else if (header == "RC")
{
- client_sock->write(sc_packet.toUtf8());
+ client_sock->sendTextMessage(sc_packet.toUtf8());
}
else if (header == "RM")
{
- client_sock->write("SM#%");
+ client_sock->sendTextMessage("SM#%");
}
else if (header == "RD")
{
- client_sock->write("DONE#%");
+ client_sock->sendTextMessage("DONE#%");
}
else if (header == "CC")
{
- client_sock->write("PV#0#CID#-1#%");
+ client_sock->sendTextMessage("PV#0#CID#-1#%");
QString packet = "CT#DEMO#" + tr("Demo file loaded. Send /play or > in OOC to begin playback.") + "#1#%";
- client_sock->write(packet.toUtf8());
+ client_sock->sendTextMessage(packet.toUtf8());
}
else if (header == "CT")
{
@@ -190,7 +184,7 @@ void DemoServer::handle_packet(AOPacket p_packet)
}
load_demo(path);
QString packet = "CT#DEMO#" + tr("Demo file loaded. Send /play or > in OOC to begin playback.") + "#1#%";
- client_sock->write(packet.toUtf8());
+ client_sock->sendTextMessage(packet.toUtf8());
reset_state();
}
else if (contents[1].startsWith("/play") || contents[1] == ">")
@@ -199,7 +193,7 @@ void DemoServer::handle_packet(AOPacket p_packet)
{
timer->start();
QString packet = "CT#DEMO#" + tr("Resuming playback.") + "#1#%";
- client_sock->write(packet.toUtf8());
+ client_sock->sendTextMessage(packet.toUtf8());
}
else
{
@@ -216,7 +210,7 @@ void DemoServer::handle_packet(AOPacket p_packet)
timer->stop();
timer->setInterval(timeleft);
QString packet = "CT#DEMO#" + tr("Pausing playback.") + "#1#%";
- client_sock->write(packet.toUtf8());
+ client_sock->sendTextMessage(packet.toUtf8());
}
else if (contents[1].startsWith("/max_wait"))
{
@@ -232,38 +226,32 @@ void DemoServer::handle_packet(AOPacket p_packet)
p_max_wait = -1;
}
m_max_wait = p_max_wait;
- QString packet = "CT#DEMO#" + tr("Setting max_wait to") + " ";
- client_sock->write(packet.toUtf8());
- client_sock->write(QString::number(m_max_wait).toUtf8());
- packet = " " + tr("milliseconds.") + "#1#%";
- client_sock->write(packet.toUtf8());
+ QString packet = "CT#DEMO#" + tr("Setting max_wait to") + " " + QString::number(m_max_wait) + " " + tr("milliseconds.") + "#1#%";
+ client_sock->sendTextMessage(packet);
}
else
{
QString packet = "CT#DEMO#" + tr("Not a valid integer!") + "#1#%";
- client_sock->write(packet.toUtf8());
+ client_sock->sendTextMessage(packet.toUtf8());
}
}
else
{
- QString packet = "CT#DEMO#" + tr("Current max_wait is") + " ";
- client_sock->write(packet.toUtf8());
- client_sock->write(QString::number(m_max_wait).toUtf8());
- packet = " " + tr("milliseconds.") + "#1#%";
- client_sock->write(packet.toUtf8());
+ QString packet = "CT#DEMO#" + tr("Current max_wait is") + " " + QString::number(m_max_wait) + tr("milliseconds.") + "#1#%";
+ client_sock->sendTextMessage(packet.toUtf8());
}
}
else if (contents[1].startsWith("/reload"))
{
load_demo(p_path);
QString packet = "CT#DEMO#" + tr("Current demo file reloaded. Send /play or > in OOC to begin playback.") + "#1#%";
- client_sock->write(packet.toUtf8());
+ client_sock->sendTextMessage(packet.toUtf8());
reset_state();
}
else if (contents[1].startsWith("/min_wait"))
{
QString packet = "CT#DEMO#" + tr("min_wait is deprecated. Use the client Settings for minimum wait instead!") + "#1#%";
- client_sock->write(packet.toUtf8());
+ client_sock->sendTextMessage(packet.toUtf8());
}
else if (contents[1].startsWith("/debug"))
{
@@ -276,31 +264,31 @@ void DemoServer::handle_packet(AOPacket p_packet)
{
debug_mode = toggle == 1;
QString packet = "CT#DEMO#" + tr("Setting debug mode to %1").arg(static_cast(debug_mode)) + "#1#%";
- client_sock->write(packet.toUtf8());
+ client_sock->sendTextMessage(packet.toUtf8());
// Debug mode disabled?
if (!debug_mode)
{
// Reset the timer
- client_sock->write("TI#4#1#0#%");
- client_sock->write("TI#4#3#0#%");
+ client_sock->sendTextMessage("TI#4#1#0#%");
+ client_sock->sendTextMessage("TI#4#3#0#%");
}
}
else
{
QString packet = "CT#DEMO#" + tr("Valid values are 1 or 0!") + "#1#%";
- client_sock->write(packet.toUtf8());
+ client_sock->sendTextMessage(packet.toUtf8());
}
}
else
{
QString packet = "CT#DEMO#" + tr("Set debug mode using /debug 1 to enable, and /debug 0 to disable, which will use the fifth timer (TI#4) to show the remaining time until next demo line.") + "#1#%";
- client_sock->write(packet.toUtf8());
+ client_sock->sendTextMessage(packet.toUtf8());
}
}
else if (contents[1].startsWith("/help"))
{
QString packet = "CT#DEMO#" + tr("Available commands:\nload, reload, play, pause, max_wait, debug, help") + "#1#%";
- client_sock->write(packet.toUtf8());
+ client_sock->sendTextMessage(packet.toUtf8());
}
}
}
@@ -395,22 +383,22 @@ void DemoServer::load_demo(QString filename)
void DemoServer::reset_state()
{
// Reset evidence list
- client_sock->write("LE##%");
+ client_sock->sendTextMessage("LE##%");
// Reset timers
- client_sock->write("TI#0#1#0#%");
- client_sock->write("TI#0#3#0#%");
- client_sock->write("TI#1#1#0#%");
- client_sock->write("TI#1#3#0#%");
- client_sock->write("TI#2#1#0#%");
- client_sock->write("TI#2#3#0#%");
- client_sock->write("TI#3#1#0#%");
- client_sock->write("TI#3#3#0#%");
- client_sock->write("TI#4#1#0#%");
- client_sock->write("TI#4#3#0#%");
+ client_sock->sendTextMessage("TI#0#1#0#%");
+ client_sock->sendTextMessage("TI#0#3#0#%");
+ client_sock->sendTextMessage("TI#1#1#0#%");
+ client_sock->sendTextMessage("TI#1#3#0#%");
+ client_sock->sendTextMessage("TI#2#1#0#%");
+ client_sock->sendTextMessage("TI#2#3#0#%");
+ client_sock->sendTextMessage("TI#3#1#0#%");
+ client_sock->sendTextMessage("TI#3#3#0#%");
+ client_sock->sendTextMessage("TI#4#1#0#%");
+ client_sock->sendTextMessage("TI#4#3#0#%");
// Set the BG to default (also breaks up the message queue)
- client_sock->write("BN#default#wit#%");
+ client_sock->sendTextMessage("BN#default#wit#%");
// Stop the wait packet timer
timer->stop();
@@ -432,7 +420,7 @@ void DemoServer::playback()
while (!current_packet.startsWith("wait#"))
{
- client_sock->write(current_packet.toUtf8());
+ client_sock->sendTextMessage(current_packet.toUtf8());
if (demo_data.isEmpty())
{
break;
@@ -478,15 +466,15 @@ void DemoServer::playback()
timer->start(duration);
if (debug_mode)
{
- client_sock->write("TI#4#2#%");
+ client_sock->sendTextMessage("TI#4#2#%");
QString debug_timer = "TI#4#0#" + QString::number(duration) + "#%";
- client_sock->write(debug_timer.toUtf8());
+ client_sock->sendTextMessage(debug_timer.toUtf8());
}
}
else
{
QString end_packet = "CT#DEMO#" + tr("Reached the end of the demo file. Send /play or > in OOC to restart, or /load to open a new file.") + "#1#%";
- client_sock->write(end_packet.toUtf8());
+ client_sock->sendTextMessage(end_packet.toUtf8());
timer->setInterval(0);
}
}
diff --git a/src/demoserver.h b/src/demoserver.h
index f52fbc7..025ffe3 100644
--- a/src/demoserver.h
+++ b/src/demoserver.h
@@ -7,9 +7,9 @@
#include
#include
#include
-#include
-#include
#include
+#include
+#include
class DemoServer : public QObject
{
@@ -27,8 +27,8 @@ private:
int m_port = 0;
int m_max_wait = -1;
- QTcpServer *tcp_server;
- QTcpSocket *client_sock = nullptr;
+ QWebSocketServer *server;
+ QWebSocket *client_sock = nullptr;
bool client_connected = false;
bool partial_packet = false;
bool debug_mode = false;
@@ -48,7 +48,7 @@ private:
private Q_SLOTS:
void accept_connection();
void destroy_connection();
- void recv_data();
+ void recv_data(const QString &in_data);
void client_disconnect();
void playback();
diff --git a/src/lobby.cpp b/src/lobby.cpp
index aba9f60..9918ca3 100644
--- a/src/lobby.cpp
+++ b/src/lobby.cpp
@@ -238,8 +238,7 @@ void Lobby::on_add_server_to_fave_released()
void Lobby::on_edit_favorite_released()
{
const int index = get_selected_server();
- ServerEditorDialog dialog;
- dialog.loadServerInfo(Options::getInstance().favorites().at(index));
+ ServerEditorDialog dialog(Options::getInstance().favorites().at(index));
if (dialog.exec())
{
Options::getInstance().updateFavorite(dialog.currentServerInfo(), index);
@@ -428,7 +427,7 @@ void Lobby::on_demo_clicked(QTreeWidgetItem *item, int column)
QString l_filepath = (get_app_path() + "/logs/%1/%2").arg(item->data(0, Qt::DisplayRole).toString(), item->data(1, Qt::DisplayRole).toString());
ao_app->demo_server->start_server();
ServerInfo demo_server;
- demo_server.ip = "127.0.0.1";
+ demo_server.address = "127.0.0.1";
demo_server.port = ao_app->demo_server->port();
ao_app->demo_server->set_demo_file(l_filepath);
net_manager->connect_to_server(demo_server);
@@ -462,7 +461,22 @@ void Lobby::list_servers()
{
QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_serverlist_tree);
treeItem->setData(0, Qt::DisplayRole, i);
- treeItem->setText(1, i_server.name);
+
+ if (i_server.legacy)
+ {
+ 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);
+ }
+ else
+ {
+ treeItem->setText(1, i_server.name);
+ }
+
i++;
}
ui_serverlist_tree->setSortingEnabled(true);
@@ -480,7 +494,22 @@ void Lobby::list_favorites()
{
QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_favorites_tree);
treeItem->setData(0, Qt::DisplayRole, i);
- treeItem->setText(1, i_server.name);
+
+ if (i_server.legacy)
+ {
+ 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);
+ }
+ else
+ {
+ treeItem->setText(1, i_server.name);
+ }
+
i++;
}
ui_favorites_tree->setSortingEnabled(true);
diff --git a/src/net/netconnection.cpp b/src/net/netconnection.cpp
deleted file mode 100644
index 63ca706..0000000
--- a/src/net/netconnection.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "netconnection.h"
-
-NetConnection::NetConnection(QObject *parent)
- : QObject(parent)
-{}
diff --git a/src/net/netconnection.h b/src/net/netconnection.h
deleted file mode 100644
index 0b5d6be..0000000
--- a/src/net/netconnection.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma once
-
-#include "aopacket.h"
-#include "datatypes.h"
-
-#include
-
-class NetConnection : public QObject
-{
- Q_OBJECT
-
-public:
- explicit NetConnection(QObject *parent = nullptr);
-
- virtual bool isConnected() = 0;
-
- virtual void connectToServer(ServerInfo &server) = 0;
- virtual void disconnectFromServer() = 0;
-
- virtual void sendPacket(AOPacket packet) = 0;
-
-Q_SIGNALS:
- void connectedToServer();
- void disconnectedFromServer();
- void errorOccurred(QString error);
-
- void receivedPacket(AOPacket packet);
-};
diff --git a/src/net/nettcpconnection.cpp b/src/net/nettcpconnection.cpp
deleted file mode 100644
index 2bc52b7..0000000
--- a/src/net/nettcpconnection.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-#include "nettcpconnection.h"
-
-NetTcpConnection::NetTcpConnection(QObject *parent)
- : NetConnection(parent)
- , m_socket(new QTcpSocket(this))
- , m_last_state(QAbstractSocket::UnconnectedState)
-{
-#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
- connect(m_socket, QOverload::of(&QAbstractSocket::error), this, &NetTcpConnection::onErrorOccurred);
-#else
- connect(m_socket, &QTcpSocket::errorOccurred, this, &NetTcpConnection::onErrorOccurred);
-#endif
- connect(m_socket, &QTcpSocket::stateChanged, this, &NetTcpConnection::onStateChanged);
- connect(m_socket, &QTcpSocket::readyRead, this, &NetTcpConnection::onReadyRead);
-}
-
-NetTcpConnection::~NetTcpConnection()
-{
- m_socket->disconnect(this);
- disconnectFromServer();
-}
-
-bool NetTcpConnection::isConnected()
-{
- return m_last_state == QAbstractSocket::ConnectedState;
-}
-
-void NetTcpConnection::connectToServer(ServerInfo &server)
-{
- disconnectedFromServer();
- m_socket->connectToHost(server.ip, server.port);
-}
-
-void NetTcpConnection::disconnectFromServer()
-{
- m_socket->abort();
-}
-
-void NetTcpConnection::sendPacket(AOPacket packet)
-{
- if (!isConnected())
- {
- qWarning().noquote() << QObject::tr("Cannot send packet, not connected to server");
- return;
- }
- m_socket->write(packet.toString(true).toUtf8());
-}
-
-void NetTcpConnection::onErrorOccurred()
-{
- Q_EMIT errorOccurred(m_socket->errorString());
-}
-
-void NetTcpConnection::onStateChanged(QAbstractSocket::SocketState state)
-{
- m_last_state = state;
- switch (state)
- {
- default:
- break;
-
- case QAbstractSocket::ConnectedState:
- m_cached_data.clear();
- Q_EMIT connectedToServer();
- break;
-
- case QAbstractSocket::UnconnectedState:
- Q_EMIT disconnectFromServer();
- break;
- }
-}
-
-void NetTcpConnection::onReadyRead()
-{
- m_cached_data += QString::fromUtf8(m_socket->readAll());
- if (!m_cached_data.endsWith('%'))
- {
- return;
- }
-
- QStringList raw_packet_list = m_cached_data.split('%', Qt::SkipEmptyParts);
- m_cached_data.clear();
- for (QString raw_packet : raw_packet_list)
- {
- if (!raw_packet.endsWith('#'))
- {
- Q_EMIT errorOccurred(QObject::tr("Malformed packet received %1").arg(raw_packet));
- continue;
- }
- raw_packet.chop(1);
-
- QStringList raw_content = raw_packet.split('#');
-
- const QString header = raw_content.takeFirst();
- for (QString &data : raw_content)
- {
- data = AOPacket::decode(data);
- }
-
- Q_EMIT receivedPacket(AOPacket(header, raw_content));
- }
-}
diff --git a/src/net/nettcpconnection.h b/src/net/nettcpconnection.h
deleted file mode 100644
index 40dae19..0000000
--- a/src/net/nettcpconnection.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#pragma once
-
-#include "aopacket.h"
-#include "datatypes.h"
-#include "netconnection.h"
-
-#include
-
-class NetTcpConnection : public NetConnection
-{
-public:
- NetTcpConnection(QObject *parent = nullptr);
- virtual ~NetTcpConnection();
-
- bool isConnected() override;
-
- void connectToServer(ServerInfo &server) override;
- void disconnectFromServer() override;
-
- void sendPacket(AOPacket packet) override;
-
-private:
- QTcpSocket *m_socket;
- QAbstractSocket::SocketState m_last_state;
- QString m_cached_data;
-
-private Q_SLOTS:
- void onErrorOccurred();
- void onStateChanged(QAbstractSocket::SocketState state);
- void onReadyRead();
-};
diff --git a/src/net/netwebsocketconnection.h b/src/net/netwebsocketconnection.h
deleted file mode 100644
index 26f41a6..0000000
--- a/src/net/netwebsocketconnection.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-
-#include "netconnection.h"
-
-class NetworkManager;
-
-#include
-
-class NetWebSocketConnection : public NetConnection
-{
-public:
- NetWebSocketConnection(NetworkManager *networkManager);
- virtual ~NetWebSocketConnection();
-
- bool isConnected() override;
-
- void connectToServer(ServerInfo &server) override;
- void disconnectFromServer() override;
-
- void sendPacket(AOPacket packet) override;
-
-private:
- NetworkManager *m_network_manager;
-
- QWebSocket *m_socket;
- QAbstractSocket::SocketState m_last_state;
-
-private Q_SLOTS:
- void onError();
- void onStateChanged(QAbstractSocket::SocketState state);
- void onTextMessageReceived(QString message);
-};
diff --git a/src/network/serverinfo.cpp b/src/network/serverinfo.cpp
new file mode 100644
index 0000000..1762866
--- /dev/null
+++ b/src/network/serverinfo.cpp
@@ -0,0 +1,6 @@
+#include "serverinfo.h"
+
+QString ServerInfo::toString() const
+{
+ return QString("%1 (%2:%3)").arg(name.isEmpty() ? QStringLiteral("Unnamed Server") : name).arg(address).arg(port);
+}
diff --git a/src/network/serverinfo.h b/src/network/serverinfo.h
new file mode 100644
index 0000000..1f13e3e
--- /dev/null
+++ b/src/network/serverinfo.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include
+
+class ServerInfo
+{
+public:
+ QString name;
+ QString description;
+ QString address;
+ quint16 port = 0;
+ bool legacy = false;
+
+ QString toString() const;
+};
diff --git a/src/net/netwebsocketconnection.cpp b/src/network/websocketconnection.cpp
similarity index 55%
rename from src/net/netwebsocketconnection.cpp
rename to src/network/websocketconnection.cpp
index 91fc526..133eae1 100644
--- a/src/net/netwebsocketconnection.cpp
+++ b/src/network/websocketconnection.cpp
@@ -1,48 +1,48 @@
-#include "netwebsocketconnection.h"
+#include "websocketconnection.h"
-#include "networkmanager.h"
+#include "aoapplication.h"
#include
#include
-NetWebSocketConnection::NetWebSocketConnection(NetworkManager *networkManager)
- : NetConnection(networkManager)
- , m_network_manager(networkManager)
+WebSocketConnection::WebSocketConnection(AOApplication *ao_app, QObject *parent)
+ : QObject(parent)
+ , ao_app(ao_app)
, m_socket(new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this))
, m_last_state(QAbstractSocket::UnconnectedState)
{
- connect(m_socket, QOverload::of(&QWebSocket::error), this, &NetWebSocketConnection::onError);
- connect(m_socket, &QWebSocket::stateChanged, this, &NetWebSocketConnection::onStateChanged);
- connect(m_socket, &QWebSocket::textMessageReceived, this, &NetWebSocketConnection::onTextMessageReceived);
+ connect(m_socket, QOverload::of(&QWebSocket::error), this, &WebSocketConnection::onError);
+ connect(m_socket, &QWebSocket::stateChanged, this, &WebSocketConnection::onStateChanged);
+ connect(m_socket, &QWebSocket::textMessageReceived, this, &WebSocketConnection::onTextMessageReceived);
}
-NetWebSocketConnection::~NetWebSocketConnection()
+WebSocketConnection::~WebSocketConnection()
{
m_socket->disconnect(this);
disconnectFromServer();
}
-bool NetWebSocketConnection::isConnected()
+bool WebSocketConnection::isConnected()
{
return m_last_state == QAbstractSocket::ConnectedState;
}
-void NetWebSocketConnection::connectToServer(ServerInfo &server)
+void WebSocketConnection::connectToServer(const ServerInfo &server)
{
disconnectFromServer();
QUrl url;
url.setScheme("ws");
- url.setHost(server.ip);
+ url.setHost(server.address);
url.setPort(server.port);
QNetworkRequest req(url);
- req.setHeader(QNetworkRequest::UserAgentHeader, m_network_manager->get_user_agent());
+ req.setHeader(QNetworkRequest::UserAgentHeader, QStringLiteral("AttorneyOnline/%1 (Desktop)").arg(ao_app->get_version_string()));
m_socket->open(req);
}
-void NetWebSocketConnection::disconnectFromServer()
+void WebSocketConnection::disconnectFromServer()
{
if (isConnected())
{
@@ -50,17 +50,17 @@ void NetWebSocketConnection::disconnectFromServer()
}
}
-void NetWebSocketConnection::sendPacket(AOPacket packet)
+void WebSocketConnection::sendPacket(AOPacket packet)
{
m_socket->sendTextMessage(packet.toString(true));
}
-void NetWebSocketConnection::onError()
+void WebSocketConnection::onError()
{
Q_EMIT errorOccurred(m_socket->errorString());
}
-void NetWebSocketConnection::onStateChanged(QAbstractSocket::SocketState state)
+void WebSocketConnection::onStateChanged(QAbstractSocket::SocketState state)
{
m_last_state = state;
switch (state)
@@ -78,7 +78,7 @@ void NetWebSocketConnection::onStateChanged(QAbstractSocket::SocketState state)
}
}
-void NetWebSocketConnection::onTextMessageReceived(QString message)
+void WebSocketConnection::onTextMessageReceived(QString message)
{
if (!message.endsWith("#%"))
{
diff --git a/src/network/websocketconnection.h b/src/network/websocketconnection.h
new file mode 100644
index 0000000..9df9a49
--- /dev/null
+++ b/src/network/websocketconnection.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "aopacket.h"
+#include "serverinfo.h"
+
+#include
+#include
+
+class AOApplication;
+
+class WebSocketConnection : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit WebSocketConnection(AOApplication *ao_app, QObject *parent = nullptr);
+ virtual ~WebSocketConnection();
+
+ bool isConnected();
+
+ void connectToServer(const ServerInfo &server);
+ void disconnectFromServer();
+
+ void sendPacket(AOPacket packet);
+
+Q_SIGNALS:
+ void connectedToServer();
+ void disconnectedFromServer();
+ void errorOccurred(QString error);
+
+ void receivedPacket(AOPacket packet);
+
+private:
+ AOApplication *ao_app;
+
+ QWebSocket *m_socket;
+ QAbstractSocket::SocketState m_last_state;
+
+private Q_SLOTS:
+ void onError();
+ void onStateChanged(QAbstractSocket::SocketState state);
+ void onTextMessageReceived(QString message);
+};
diff --git a/src/networkmanager.cpp b/src/networkmanager.cpp
index b574b63..fc30060 100644
--- a/src/networkmanager.cpp
+++ b/src/networkmanager.cpp
@@ -3,8 +3,6 @@
#include "datatypes.h"
#include "debug_functions.h"
#include "lobby.h"
-#include "net/nettcpconnection.h"
-#include "net/netwebsocketconnection.h"
#include "options.h"
#include
@@ -59,19 +57,19 @@ void NetworkManager::ms_request_finished(QNetworkReply *reply)
{
const auto entry = entryRef.toObject();
ServerInfo server;
- server.ip = entry["ip"].toString();
+ server.address = entry["ip"].toString();
server.name = entry["name"].toString();
server.description = entry["description"].toString(tr("No description provided."));
- if (entry["ws_port"].isDouble())
+ if (entry.contains("ws_port"))
{
- server.socket_type = WebSocketServerConnection;
server.port = entry["ws_port"].toInt();
}
else
{
- server.socket_type = TcpServerConnection;
server.port = entry["port"].toInt();
+ server.legacy = true;
}
+
if (server.port != 0)
{
server_list.append(server);
@@ -149,27 +147,12 @@ void NetworkManager::connect_to_server(ServerInfo server)
disconnect_from_server();
qInfo().noquote() << QObject::tr("Connecting to %1").arg(server.toString());
- switch (server.socket_type)
- {
- default:
- server.socket_type = TcpServerConnection;
- [[fallthrough]];
+ m_connection = new WebSocketConnection(ao_app, this);
- case TcpServerConnection:
- qInfo() << "Using TCP backend.";
- m_connection = new NetTcpConnection(this);
- break;
-
- case WebSocketServerConnection:
- qInfo() << "Using WebSockets backend.";
- m_connection = new NetWebSocketConnection(this);
- break;
- }
-
- connect(m_connection, &NetConnection::connectedToServer, this, [] { qInfo() << "Established connection to server."; });
- connect(m_connection, &NetConnection::disconnectedFromServer, ao_app, &AOApplication::server_disconnected);
- connect(m_connection, &NetConnection::errorOccurred, this, [](QString error) { qCritical() << "Connection error:" << error; });
- connect(m_connection, &NetConnection::receivedPacket, this, &NetworkManager::handle_server_packet);
+ connect(m_connection, &WebSocketConnection::connectedToServer, this, [] { qInfo() << "Established connection to server."; });
+ connect(m_connection, &WebSocketConnection::disconnectedFromServer, ao_app, &AOApplication::server_disconnected);
+ connect(m_connection, &WebSocketConnection::errorOccurred, this, [](QString error) { qCritical() << "Connection error:" << error; });
+ connect(m_connection, &WebSocketConnection::receivedPacket, this, &NetworkManager::handle_server_packet);
m_connection->connectToServer(server);
}
diff --git a/src/networkmanager.h b/src/networkmanager.h
index 4ec539f..8f2d8d4 100644
--- a/src/networkmanager.h
+++ b/src/networkmanager.h
@@ -2,7 +2,7 @@
#include "aoapplication.h"
#include "aopacket.h"
-#include "net/netconnection.h"
+#include "network/websocketconnection.h"
#include
#include
@@ -50,7 +50,7 @@ private:
AOApplication *ao_app;
QNetworkAccessManager *http;
- NetConnection *m_connection = nullptr;
+ WebSocketConnection *m_connection = nullptr;
QTimer *heartbeat_timer;
diff --git a/src/options.cpp b/src/options.cpp
index d06c5e4..9145aa4 100644
--- a/src/options.cpp
+++ b/src/options.cpp
@@ -668,11 +668,19 @@ QVector Options::favorites()
{
ServerInfo f_server;
favorite.beginGroup(group);
- f_server.ip = favorite.value("address", "127.0.0.1").toString();
+ f_server.address = favorite.value("address", "127.0.0.1").toString();
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();
- f_server.socket_type = SERVER_CONNECTION_TYPE_STRING_MAP.value(favorite.value("protocol", "tcp").toString());
+ if (favorite.contains("protocol"))
+ {
+ f_server.legacy = favorite.value("protocol").toString() == "tcp";
+ }
+ else
+ {
+ f_server.legacy = favorite.value("legacy", false).toBool();
+ }
+
serverlist.append(std::move(f_server));
favorite.endGroup();
}
@@ -688,18 +696,10 @@ void Options::setFavorites(QVector value)
auto fav_server = value.at(i);
favorite.beginGroup(QString::number(i));
favorite.setValue("name", fav_server.name);
- favorite.setValue("address", fav_server.ip);
+ favorite.setValue("address", fav_server.address);
favorite.setValue("port", fav_server.port);
favorite.setValue("desc", fav_server.description);
-
- if (fav_server.socket_type == TcpServerConnection)
- {
- favorite.setValue("protocol", "tcp");
- }
- else
- {
- favorite.setValue("protocol", "ws");
- }
+ favorite.setValue("legacy", fav_server.legacy);
favorite.endGroup();
}
favorite.sync();
@@ -717,17 +717,10 @@ void Options::addFavorite(ServerInfo server)
int index = favorites().size();
favorite.beginGroup(QString::number(index));
favorite.setValue("name", server.name);
- favorite.setValue("address", server.ip);
+ favorite.setValue("address", server.address);
favorite.setValue("port", server.port);
favorite.setValue("desc", server.description);
- if (server.socket_type == TcpServerConnection)
- {
- favorite.setValue("protocol", "tcp");
- }
- else
- {
- favorite.setValue("protocol", "ws");
- }
+ favorite.setValue("legacy", server.legacy);
favorite.endGroup();
favorite.sync();
}
@@ -736,17 +729,10 @@ void Options::updateFavorite(ServerInfo server, int index)
{
favorite.beginGroup(QString::number(index));
favorite.setValue("name", server.name);
- favorite.setValue("address", server.ip);
+ favorite.setValue("address", server.address);
favorite.setValue("port", server.port);
favorite.setValue("desc", server.description);
- if (server.socket_type == TcpServerConnection)
- {
- favorite.setValue("protocol", "tcp");
- }
- else
- {
- favorite.setValue("protocol", "ws");
- }
+ favorite.setValue("legacy", server.legacy);
favorite.endGroup();
favorite.sync();
}
diff --git a/src/options.h b/src/options.h
index 1ea7621..4ccc301 100644
--- a/src/options.h
+++ b/src/options.h
@@ -1,8 +1,9 @@
#pragma once
+#include "network/serverinfo.h"
+
#include
#include
-#include
class Options
{
diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp
index 8b86b34..f440a0c 100644
--- a/src/packet_distribution.cpp
+++ b/src/packet_distribution.cpp
@@ -132,7 +132,7 @@ void AOApplication::server_packet_received(AOPacket packet)
{
auto info = server_list.at(selected_server);
server_name = info.name;
- server_address = QString("%1:%2").arg(info.ip, QString::number(info.port));
+ server_address = QString("%1:%2").arg(info.address, QString::number(info.port));
window_title = server_name;
}
break;
@@ -144,7 +144,7 @@ void AOApplication::server_packet_received(AOPacket packet)
{
auto info = favorite_list.at(selected_server);
server_name = info.name;
- server_address = QString("%1:%2").arg(info.ip, QString::number(info.port));
+ server_address = QString("%1:%2").arg(info.address, QString::number(info.port));
window_title = server_name;
}
}
diff --git a/src/widgets/direct_connect_dialog.cpp b/src/widgets/direct_connect_dialog.cpp
index db4cde6..6a09b77 100644
--- a/src/widgets/direct_connect_dialog.cpp
+++ b/src/widgets/direct_connect_dialog.cpp
@@ -50,27 +50,29 @@ void DirectConnectDialog::onConnectPressed()
QString l_hostname = ui_direct_hostname_edit->text();
if (!SCHEME_PATTERN.match(l_hostname).hasMatch())
{
- l_hostname = "tcp://" % l_hostname;
+ l_hostname = "ws://" % l_hostname;
}
+
QUrl l_url(l_hostname);
if (!l_url.isValid())
{
call_error(tr("Invalid URL."));
return;
}
- if (!SERVER_CONNECTION_TYPE_STRING_MAP.contains(l_url.scheme()))
+
+ if (l_url.scheme() != "ws")
{
- call_error(tr("Scheme not recognized. Must be either of the following: ") % QStringList::fromVector(SERVER_CONNECTION_TYPE_STRING_MAP.keys().toVector()).join(", "));
+ call_error(tr("Invalid URL scheme. Only ws:// is supported."));
return;
}
+
if (l_url.port() == -1)
{
call_error(tr("Invalid server port."));
return;
}
ServerInfo l_server;
- l_server.socket_type = SERVER_CONNECTION_TYPE_STRING_MAP[l_url.scheme()];
- l_server.ip = l_url.host();
+ l_server.address = l_url.host();
l_server.port = l_url.port();
l_server.name = "Direct Connection";
diff --git a/src/widgets/server_editor_dialog.cpp b/src/widgets/server_editor_dialog.cpp
index 386950e..150a435 100644
--- a/src/widgets/server_editor_dialog.cpp
+++ b/src/widgets/server_editor_dialog.cpp
@@ -1,6 +1,7 @@
#include "server_editor_dialog.h"
#include "datatypes.h"
+#include "debug_functions.h"
#include "gui_utils.h"
#include "options.h"
@@ -30,7 +31,6 @@ ServerEditorDialog::ServerEditorDialog(QWidget *parent)
FROM_UI(QLineEdit, name);
FROM_UI(QLineEdit, hostname);
FROM_UI(QSpinBox, port);
- FROM_UI(QComboBox, protocol);
FROM_UI(QPlainTextEdit, description);
FROM_UI(QDialogButtonBox, button_box);
@@ -43,52 +43,35 @@ ServerEditorDialog::ServerEditorDialog(QWidget *parent)
connect(ui_button_box, &QDialogButtonBox::rejected, this, &ServerEditorDialog::reject);
}
+ServerEditorDialog::ServerEditorDialog(const ServerInfo &server, QWidget *parent)
+ : ServerEditorDialog(parent)
+{
+ ui_name->setText(server.name);
+ ui_hostname->setText(server.address);
+ ui_port->setValue(server.port);
+ ui_description->setPlainText(server.description);
+}
+
ServerInfo ServerEditorDialog::currentServerInfo() const
{
ServerInfo server;
server.name = ui_name->text();
- server.ip = ui_hostname->text();
+ server.address = ui_hostname->text();
server.port = ui_port->value();
server.description = ui_description->toPlainText();
- server.socket_type = ServerConnectionType(ui_protocol->currentIndex());
return server;
}
-void ServerEditorDialog::loadServerInfo(ServerInfo server)
-{
- ui_name->setText(server.name);
- ui_hostname->setText(server.ip);
- ui_port->setValue(server.port);
- ui_description->setPlainText(server.description);
- ui_protocol->setCurrentIndex(server.socket_type);
-}
-
void ServerEditorDialog::parseLegacyEntry()
{
QStringList entry = ui_legacy_edit->text().split(":");
- ServerInfo l_server_entry;
- if (entry.isEmpty())
+ if (entry.size() < 3)
{
- qDebug() << "Legacy entry empty.";
+ call_error("Invalid legacy server entry");
return;
}
- int item_count = entry.size();
- if (item_count >= 3)
- {
- ui_hostname->setText(entry.at(0));
- ui_port->setValue(entry.at(1).toInt());
- ui_name->setText(entry.at(2));
- if (item_count >= 4)
- {
- if (entry.at(3) == "ws")
- {
- ui_protocol->setCurrentIndex(1);
- }
- else
- {
- ui_protocol->setCurrentIndex(0);
- }
- }
- }
+ ui_hostname->setText(entry.at(0));
+ ui_port->setValue(entry.at(1).toInt());
+ ui_name->setText(entry.at(2));
}
diff --git a/src/widgets/server_editor_dialog.h b/src/widgets/server_editor_dialog.h
index 1ceb352..a8844d4 100644
--- a/src/widgets/server_editor_dialog.h
+++ b/src/widgets/server_editor_dialog.h
@@ -1,6 +1,6 @@
#pragma once
-#include "datatypes.h"
+#include "network/serverinfo.h"
#include
#include
@@ -21,8 +21,6 @@ public:
ServerInfo currentServerInfo() const;
- void loadServerInfo(ServerInfo server);
-
private:
static const QString UI_FILE_PATH;
@@ -31,7 +29,6 @@ private:
QLineEdit *ui_name;
QLineEdit *ui_hostname;
QSpinBox *ui_port;
- QComboBox *ui_protocol;
QPlainTextEdit *ui_description;
QDialogButtonBox *ui_button_box;