Skip to content

Commit

Permalink
Removed TCP server entry point (#364)
Browse files Browse the repository at this point in the history
* Removed TCP server

Resolve AttorneyOnline/AO2-Client#987, resolve AttorneyOnline/AO2-Client#1007

* Remove ini key, remove obsolete test

---------

Co-authored-by: Salanto <[email protected]>
  • Loading branch information
TrickyLeifa and Salanto authored Jul 14, 2024
1 parent 040f5a3 commit 1edc80a
Show file tree
Hide file tree
Showing 14 changed files with 52 additions and 318 deletions.
5 changes: 1 addition & 4 deletions bin/config_sample/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
; The maximum number of players that can join the server at once.
max_players=100

; The TCP port to listen for incoming connections on.
; The port to listen for incoming connections on.
port=27016

; The server description that will appear on the master server.
Expand All @@ -17,9 +17,6 @@ motd=MOTD is not set.
; Whether the server should accept WebAO connections or not.
webao_enable=true

; The TCP port to listen for WebAO connections on. This must be different than the server port.
webao_port=27017

; The authorization level of the server. You shouldn't touch this, use /changeauth on the server instead.
auth=simple

Expand Down
5 changes: 1 addition & 4 deletions bin_tests/config/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
; The maximum number of players that can join the server at once.
max_players=100

; The TCP port to listen for incoming connections on.
; The port to listen for incoming connections on.
port=27016

; The server description that will appear on the master server.
Expand All @@ -17,9 +17,6 @@ motd=MOTD is not set.
; Whether the server should accept WebAO connections or not.
webao_enable=true

; The TCP port to listen for WebAO connections on. This must be different than the server port.
webao_port=27017

; The authorization level of the server. You shouldn't touch this, use /changeauth on the server instead.
auth=simple

Expand Down
8 changes: 5 additions & 3 deletions src/advertiser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

#include "config_manager.h"

Advertiser::Advertiser()
Advertiser::Advertiser(int port)
{
m_manager = new QNetworkAccessManager();
connect(m_manager, &QNetworkAccessManager::finished,
Expand All @@ -28,15 +28,17 @@ Advertiser::Advertiser()
m_name = ConfigManager::serverName();
m_hostname = ConfigManager::advertiserHostname();
m_description = ConfigManager::serverDescription();
m_port = ConfigManager::serverPort();

// Cheap workaround to correctly advertise when Cloudflare tunnel is used.
if (ConfigManager::advertiserCloudflareMode()) {
m_port = 80;
m_ws_port = 80;
}
else {
m_ws_port = ConfigManager::webaoPort();
m_port = port;
m_ws_port = port;
}

m_masterserver = ConfigManager::advertiserIP();
m_debug = ConfigManager::advertiserDebug();
}
Expand Down
2 changes: 1 addition & 1 deletion src/advertiser.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Advertiser : public QObject
/**
* @brief Constructor for the HTTP_Advertiser class.
*/
explicit Advertiser();
explicit Advertiser(int port);

/**
* @brief Deconstructor for the HTTP_Advertiser class. Yes, that's it. Can't say more about it.
Expand Down
2 changes: 1 addition & 1 deletion src/aoclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ class AOClient : public QObject
QString m_hwid;

/**
* @brief The network socket used by the client. Can either be a Websocket or TCP Socket.
* @brief The network socket used by the client.
*/
NetworkSocket *m_socket;

Expand Down
10 changes: 5 additions & 5 deletions src/config_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,11 @@ int ConfigManager::maxPlayers()

int ConfigManager::serverPort()
{
if (m_settings->contains("Options/webao_port")) {
qWarning("webao_port is deprecated, use port instead");
return m_settings->value("Options/webao_port", 27016).toInt();
}

return m_settings->value("Options/port", 27016).toInt();
}

Expand All @@ -345,11 +350,6 @@ bool ConfigManager::webaoEnabled()
return m_settings->value("Options/webao_enable", false).toBool();
}

int ConfigManager::webaoPort()
{
return m_settings->value("Options/webao_port", 27017).toInt();
}

DataTypes::AuthType ConfigManager::authType()
{
QString l_auth = m_settings->value("Options/auth", "simple").toString().toUpper();
Expand Down
9 changes: 1 addition & 8 deletions src/config_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class ConfigManager
static bool verifyServerConfig();

/**
* @brief Returns the IP the TCP Server binds to.
* @brief Returns the IP the server binds to.
*
* @return See short description
*/
Expand Down Expand Up @@ -171,13 +171,6 @@ class ConfigManager
*/
static bool webaoEnabled();

/**
* @brief Returns the port to listen for webAO connections on.
*
* @return See short description.
*/
static int webaoPort();

/**
* @brief Returns the server's authorization type.
*
Expand Down
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ int main(int argc, char *argv[])
QCoreApplication::quit();
}
else {
server = new Server(ConfigManager::serverPort(), ConfigManager::webaoPort());
server = new Server(ConfigManager::serverPort());
server->start();
}

Expand Down
90 changes: 12 additions & 78 deletions src/network/network_socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,19 @@
#include "network/network_socket.h"
#include "packet/packet_factory.h"

NetworkSocket::NetworkSocket(QTcpSocket *f_socket, QObject *parent) :
QObject(parent)
{
m_socket_type = TCP;
m_client_socket.tcp = f_socket;
connect(m_client_socket.tcp, &QTcpSocket::readyRead,
this, &NetworkSocket::readData);
connect(m_client_socket.tcp, &QTcpSocket::disconnected,
this, &NetworkSocket::clientDisconnected);
m_socket_ip = m_client_socket.tcp->peerAddress();
}

NetworkSocket::NetworkSocket(QWebSocket *f_socket, QObject *parent) :
QObject(parent)
{
m_socket_type = WS;
m_client_socket.ws = f_socket;
connect(m_client_socket.ws, &QWebSocket::textMessageReceived,
this, &NetworkSocket::ws_readData);
connect(m_client_socket.ws, &QWebSocket::disconnected,
this, &NetworkSocket::clientDisconnected);
m_client_socket = f_socket;
connect(m_client_socket, &QWebSocket::textMessageReceived, this, &NetworkSocket::handleMessage);
connect(m_client_socket, &QWebSocket::disconnected, this, &NetworkSocket::clientDisconnected);

bool l_is_local = (m_client_socket.ws->peerAddress() == QHostAddress::LocalHost) ||
(m_client_socket.ws->peerAddress() == QHostAddress::LocalHostIPv6) ||
(m_client_socket.ws->peerAddress() == QHostAddress("::ffff:127.0.0.1"));
bool l_is_local = (m_client_socket->peerAddress() == QHostAddress::LocalHost) ||
(m_client_socket->peerAddress() == QHostAddress::LocalHostIPv6) ||
(m_client_socket->peerAddress() == QHostAddress("::ffff:127.0.0.1"));
// TLDR : We check if the header comes trough a proxy/tunnel running locally.
// This is to ensure nobody can send those headers from the web.
QNetworkRequest l_request = m_client_socket.ws->request();
QNetworkRequest l_request = m_client_socket->request();
if (l_request.hasRawHeader("x-forwarded-for") && l_is_local) {
m_socket_ip = QHostAddress(QString::fromUtf8(l_request.rawHeader("x-forwarded-for")));
}
Expand All @@ -56,69 +41,25 @@ NetworkSocket::NetworkSocket(QWebSocket *f_socket, QObject *parent) :

NetworkSocket::~NetworkSocket()
{
if (m_socket_type == TCP) {
m_client_socket.tcp->deleteLater();
}
else {
m_client_socket.ws->deleteLater();
}
m_client_socket->deleteLater();
}

QHostAddress NetworkSocket::peerAddress()
{
return m_socket_ip;
}

void NetworkSocket::close()
{
if (m_socket_type == TCP) {
m_client_socket.tcp->deleteLater();
}
else {
m_client_socket.ws->deleteLater();
}
}

void NetworkSocket::close(QWebSocketProtocol::CloseCode f_code)
{
m_client_socket.ws->close(f_code);
}

void NetworkSocket::readData()
{
if (m_client_socket.tcp->bytesAvailable() > 30720) { // Client can send a max of 30KB to the server.
m_client_socket.tcp->close();
}

QString l_data = QString::fromUtf8(m_client_socket.tcp->readAll());

if (m_is_partial) {
l_data = m_partial_packet + l_data;
}
if (!l_data.endsWith("%")) {
m_is_partial = true;
}

QStringList l_all_packets = l_data.split("%");
l_all_packets.removeLast(); // Remove the entry after the last delimiter

for (const QString &l_single_packet : qAsConst(l_all_packets)) {
AOPacket *l_packet = PacketFactory::createPacket(l_single_packet);
if (!l_packet) {
qDebug() << "Unimplemented packet: " << l_single_packet;
continue;
}

emit handlePacket(l_packet);
}
m_client_socket->close(f_code);
}

void NetworkSocket::ws_readData(QString f_data)
void NetworkSocket::handleMessage(QString f_data)
{
QString l_data = f_data;

if (l_data.toUtf8().size() > 30720) {
m_client_socket.ws->close(QWebSocketProtocol::CloseCodeTooMuchData);
m_client_socket->close(QWebSocketProtocol::CloseCodeTooMuchData);
}

QStringList l_all_packets = l_data.split("%");
Expand All @@ -142,12 +83,5 @@ void NetworkSocket::ws_readData(QString f_data)

void NetworkSocket::write(AOPacket *f_packet)
{
if (m_socket_type == TCP) {
m_client_socket.tcp->write(f_packet->toUtf8());
m_client_socket.tcp->flush();
}
else {
m_client_socket.ws->sendTextMessage(f_packet->toString());
m_client_socket.ws->flush();
}
m_client_socket->sendTextMessage(f_packet->toString());
}
60 changes: 3 additions & 57 deletions src/network/network_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

#include <QHostAddress>
#include <QObject>
#include <QTcpSocket>
#include <QWebSocket>

#include "network/aopacket.h"
Expand All @@ -32,13 +31,6 @@ class NetworkSocket : public QObject
Q_OBJECT

public:
/**
* @brief Constructor for the network socket class.
* @param QTcpSocket for communication with external AO2-Client
* @param Pointer to the server object.
*/
NetworkSocket(QTcpSocket *f_socket, QObject *parent = nullptr);

/**
* @brief Constructor for the network socket class.
* @param QWebSocket for communication with external AO2-Client or WebAO clients.
Expand All @@ -58,17 +50,12 @@ class NetworkSocket : public QObject
*/
QHostAddress peerAddress();

/**
* @brief Closes the socket by request of the child AOClient object or the server.
*/
void close();

/**
* @brief Closes the socket by request of the child AOClient object or the server.
*
* @param The close code to the send to the client.
*/
void close(QWebSocketProtocol::CloseCode f_code);
void close(QWebSocketProtocol::CloseCode f_code = QWebSocketProtocol::CloseCodeNormal);

/**
* @brief Writes data to the network socket.
Expand All @@ -78,7 +65,6 @@ class NetworkSocket : public QObject
void write(AOPacket *f_packet);

signals:

/**
* @brief handlePacket
* @param f_packet
Expand All @@ -91,62 +77,22 @@ class NetworkSocket : public QObject
void clientDisconnected();

private slots:
/**
* @brief Handles the reading and processing of TCP stream data.
*
* @return Decoded AOPacket to be processed by the child AOClient object.
*/
void readData();

/**
* @brief Handles the processing of WebSocket data.
*
* @return Decoded AOPacket to be processed by the child AOClient object.
*/
void ws_readData(QString f_data);
void handleMessage(QString f_data);

private:
enum SocketType
{
TCP,
WS
};

/**
* @brief Union holding either a TCP- or Websocket.
*/
union {
QTcpSocket *tcp;
QWebSocket *ws;
} m_client_socket;
QWebSocket *m_client_socket;

/**
* @brief Remote IP of the client.
*
* @details In the case of the WebSocket we also check if this has been proxy forwarded.
*/
QHostAddress m_socket_ip;

/**
* @brief Defines if the client is a Websocket or TCP client.
*/
SocketType m_socket_type;

/**
* @brief Filled with part of a packet if said packet could not be read fully from the client's socket.
*
* @details Per AO2's network protocol, a packet is finished with the character `%`.
*
* @see #is_partial
*/
QString m_partial_packet;

/**
* @brief True when the previous `readAll()` call from the client's socket returned an unfinished packet.
*
* @see #partial_packet
*/
bool m_is_partial;
};

#endif
6 changes: 6 additions & 0 deletions src/packet/packet_id.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ void PacketID::handlePacket(AreaData *area, AOClient &client) const
client.m_version.release = 2;
client.m_version.major = 10;
client.m_version.minor = 0;

if (!ConfigManager::webaoEnabled()) {
client.sendPacket("BD", {"WebAO is disabled on this server."});
client.m_socket->close();
return;
}
}

if (client.m_version.release != 2) {
Expand Down
Loading

0 comments on commit 1edc80a

Please sign in to comment.