Removed TCP server entry point (#364)
* Removed TCP server Resolve AttorneyOnline/AO2-Client#987, resolve AttorneyOnline/AO2-Client#1007 * Remove ini key, remove obsolete test --------- Co-authored-by: Salanto <62221668+Salanto@users.noreply.github.com>
This commit is contained in:
parent
040f5a3216
commit
1edc80a0bc
@ -2,7 +2,7 @@
|
|||||||
; The maximum number of players that can join the server at once.
|
; The maximum number of players that can join the server at once.
|
||||||
max_players=100
|
max_players=100
|
||||||
|
|
||||||
; The TCP port to listen for incoming connections on.
|
; The port to listen for incoming connections on.
|
||||||
port=27016
|
port=27016
|
||||||
|
|
||||||
; The server description that will appear on the master server.
|
; The server description that will appear on the master server.
|
||||||
@ -17,9 +17,6 @@ motd=MOTD is not set.
|
|||||||
; Whether the server should accept WebAO connections or not.
|
; Whether the server should accept WebAO connections or not.
|
||||||
webao_enable=true
|
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.
|
; The authorization level of the server. You shouldn't touch this, use /changeauth on the server instead.
|
||||||
auth=simple
|
auth=simple
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
; The maximum number of players that can join the server at once.
|
; The maximum number of players that can join the server at once.
|
||||||
max_players=100
|
max_players=100
|
||||||
|
|
||||||
; The TCP port to listen for incoming connections on.
|
; The port to listen for incoming connections on.
|
||||||
port=27016
|
port=27016
|
||||||
|
|
||||||
; The server description that will appear on the master server.
|
; The server description that will appear on the master server.
|
||||||
@ -17,9 +17,6 @@ motd=MOTD is not set.
|
|||||||
; Whether the server should accept WebAO connections or not.
|
; Whether the server should accept WebAO connections or not.
|
||||||
webao_enable=true
|
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.
|
; The authorization level of the server. You shouldn't touch this, use /changeauth on the server instead.
|
||||||
auth=simple
|
auth=simple
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include "config_manager.h"
|
#include "config_manager.h"
|
||||||
|
|
||||||
Advertiser::Advertiser()
|
Advertiser::Advertiser(int port)
|
||||||
{
|
{
|
||||||
m_manager = new QNetworkAccessManager();
|
m_manager = new QNetworkAccessManager();
|
||||||
connect(m_manager, &QNetworkAccessManager::finished,
|
connect(m_manager, &QNetworkAccessManager::finished,
|
||||||
@ -28,15 +28,17 @@ Advertiser::Advertiser()
|
|||||||
m_name = ConfigManager::serverName();
|
m_name = ConfigManager::serverName();
|
||||||
m_hostname = ConfigManager::advertiserHostname();
|
m_hostname = ConfigManager::advertiserHostname();
|
||||||
m_description = ConfigManager::serverDescription();
|
m_description = ConfigManager::serverDescription();
|
||||||
m_port = ConfigManager::serverPort();
|
|
||||||
|
|
||||||
// Cheap workaround to correctly advertise when Cloudflare tunnel is used.
|
// Cheap workaround to correctly advertise when Cloudflare tunnel is used.
|
||||||
if (ConfigManager::advertiserCloudflareMode()) {
|
if (ConfigManager::advertiserCloudflareMode()) {
|
||||||
|
m_port = 80;
|
||||||
m_ws_port = 80;
|
m_ws_port = 80;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_ws_port = ConfigManager::webaoPort();
|
m_port = port;
|
||||||
|
m_ws_port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_masterserver = ConfigManager::advertiserIP();
|
m_masterserver = ConfigManager::advertiserIP();
|
||||||
m_debug = ConfigManager::advertiserDebug();
|
m_debug = ConfigManager::advertiserDebug();
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ class Advertiser : public QObject
|
|||||||
/**
|
/**
|
||||||
* @brief Constructor for the HTTP_Advertiser class.
|
* @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.
|
* @brief Deconstructor for the HTTP_Advertiser class. Yes, that's it. Can't say more about it.
|
||||||
|
@ -328,7 +328,7 @@ class AOClient : public QObject
|
|||||||
QString m_hwid;
|
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;
|
NetworkSocket *m_socket;
|
||||||
|
|
||||||
|
@ -322,6 +322,11 @@ int ConfigManager::maxPlayers()
|
|||||||
|
|
||||||
int ConfigManager::serverPort()
|
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();
|
return m_settings->value("Options/port", 27016).toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,11 +350,6 @@ bool ConfigManager::webaoEnabled()
|
|||||||
return m_settings->value("Options/webao_enable", false).toBool();
|
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()
|
DataTypes::AuthType ConfigManager::authType()
|
||||||
{
|
{
|
||||||
QString l_auth = m_settings->value("Options/auth", "simple").toString().toUpper();
|
QString l_auth = m_settings->value("Options/auth", "simple").toString().toUpper();
|
||||||
|
@ -53,7 +53,7 @@ class ConfigManager
|
|||||||
static bool verifyServerConfig();
|
static bool verifyServerConfig();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the IP the TCP Server binds to.
|
* @brief Returns the IP the server binds to.
|
||||||
*
|
*
|
||||||
* @return See short description
|
* @return See short description
|
||||||
*/
|
*/
|
||||||
@ -171,13 +171,6 @@ class ConfigManager
|
|||||||
*/
|
*/
|
||||||
static bool webaoEnabled();
|
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.
|
* @brief Returns the server's authorization type.
|
||||||
*
|
*
|
||||||
|
@ -45,7 +45,7 @@ int main(int argc, char *argv[])
|
|||||||
QCoreApplication::quit();
|
QCoreApplication::quit();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
server = new Server(ConfigManager::serverPort(), ConfigManager::webaoPort());
|
server = new Server(ConfigManager::serverPort());
|
||||||
server->start();
|
server->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,34 +18,19 @@
|
|||||||
#include "network/network_socket.h"
|
#include "network/network_socket.h"
|
||||||
#include "packet/packet_factory.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) :
|
NetworkSocket::NetworkSocket(QWebSocket *f_socket, QObject *parent) :
|
||||||
QObject(parent)
|
QObject(parent)
|
||||||
{
|
{
|
||||||
m_socket_type = WS;
|
m_client_socket = f_socket;
|
||||||
m_client_socket.ws = f_socket;
|
connect(m_client_socket, &QWebSocket::textMessageReceived, this, &NetworkSocket::handleMessage);
|
||||||
connect(m_client_socket.ws, &QWebSocket::textMessageReceived,
|
connect(m_client_socket, &QWebSocket::disconnected, this, &NetworkSocket::clientDisconnected);
|
||||||
this, &NetworkSocket::ws_readData);
|
|
||||||
connect(m_client_socket.ws, &QWebSocket::disconnected,
|
|
||||||
this, &NetworkSocket::clientDisconnected);
|
|
||||||
|
|
||||||
bool l_is_local = (m_client_socket.ws->peerAddress() == QHostAddress::LocalHost) ||
|
bool l_is_local = (m_client_socket->peerAddress() == QHostAddress::LocalHost) ||
|
||||||
(m_client_socket.ws->peerAddress() == QHostAddress::LocalHostIPv6) ||
|
(m_client_socket->peerAddress() == QHostAddress::LocalHostIPv6) ||
|
||||||
(m_client_socket.ws->peerAddress() == QHostAddress("::ffff:127.0.0.1"));
|
(m_client_socket->peerAddress() == QHostAddress("::ffff:127.0.0.1"));
|
||||||
// TLDR : We check if the header comes trough a proxy/tunnel running locally.
|
// 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.
|
// 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) {
|
if (l_request.hasRawHeader("x-forwarded-for") && l_is_local) {
|
||||||
m_socket_ip = QHostAddress(QString::fromUtf8(l_request.rawHeader("x-forwarded-for")));
|
m_socket_ip = QHostAddress(QString::fromUtf8(l_request.rawHeader("x-forwarded-for")));
|
||||||
}
|
}
|
||||||
@ -56,12 +41,7 @@ NetworkSocket::NetworkSocket(QWebSocket *f_socket, QObject *parent) :
|
|||||||
|
|
||||||
NetworkSocket::~NetworkSocket()
|
NetworkSocket::~NetworkSocket()
|
||||||
{
|
{
|
||||||
if (m_socket_type == TCP) {
|
m_client_socket->deleteLater();
|
||||||
m_client_socket.tcp->deleteLater();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_client_socket.ws->deleteLater();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QHostAddress NetworkSocket::peerAddress()
|
QHostAddress NetworkSocket::peerAddress()
|
||||||
@ -69,56 +49,17 @@ QHostAddress NetworkSocket::peerAddress()
|
|||||||
return m_socket_ip;
|
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)
|
void NetworkSocket::close(QWebSocketProtocol::CloseCode f_code)
|
||||||
{
|
{
|
||||||
m_client_socket.ws->close(f_code);
|
m_client_socket->close(f_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkSocket::readData()
|
void NetworkSocket::handleMessage(QString f_data)
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NetworkSocket::ws_readData(QString f_data)
|
|
||||||
{
|
{
|
||||||
QString l_data = f_data;
|
QString l_data = f_data;
|
||||||
|
|
||||||
if (l_data.toUtf8().size() > 30720) {
|
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("%");
|
QStringList l_all_packets = l_data.split("%");
|
||||||
@ -142,12 +83,5 @@ void NetworkSocket::ws_readData(QString f_data)
|
|||||||
|
|
||||||
void NetworkSocket::write(AOPacket *f_packet)
|
void NetworkSocket::write(AOPacket *f_packet)
|
||||||
{
|
{
|
||||||
if (m_socket_type == TCP) {
|
m_client_socket->sendTextMessage(f_packet->toString());
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTcpSocket>
|
|
||||||
#include <QWebSocket>
|
#include <QWebSocket>
|
||||||
|
|
||||||
#include "network/aopacket.h"
|
#include "network/aopacket.h"
|
||||||
@ -32,13 +31,6 @@ class NetworkSocket : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
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.
|
* @brief Constructor for the network socket class.
|
||||||
* @param QWebSocket for communication with external AO2-Client or WebAO clients.
|
* @param QWebSocket for communication with external AO2-Client or WebAO clients.
|
||||||
@ -58,17 +50,12 @@ class NetworkSocket : public QObject
|
|||||||
*/
|
*/
|
||||||
QHostAddress peerAddress();
|
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.
|
* @brief Closes the socket by request of the child AOClient object or the server.
|
||||||
*
|
*
|
||||||
* @param The close code to the send to the client.
|
* @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.
|
* @brief Writes data to the network socket.
|
||||||
@ -78,7 +65,6 @@ class NetworkSocket : public QObject
|
|||||||
void write(AOPacket *f_packet);
|
void write(AOPacket *f_packet);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief handlePacket
|
* @brief handlePacket
|
||||||
* @param f_packet
|
* @param f_packet
|
||||||
@ -91,34 +77,15 @@ class NetworkSocket : public QObject
|
|||||||
void clientDisconnected();
|
void clientDisconnected();
|
||||||
|
|
||||||
private slots:
|
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.
|
* @brief Handles the processing of WebSocket data.
|
||||||
*
|
*
|
||||||
* @return Decoded AOPacket to be processed by the child AOClient object.
|
* @return Decoded AOPacket to be processed by the child AOClient object.
|
||||||
*/
|
*/
|
||||||
void ws_readData(QString f_data);
|
void handleMessage(QString f_data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum SocketType
|
QWebSocket *m_client_socket;
|
||||||
{
|
|
||||||
TCP,
|
|
||||||
WS
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Union holding either a TCP- or Websocket.
|
|
||||||
*/
|
|
||||||
union {
|
|
||||||
QTcpSocket *tcp;
|
|
||||||
QWebSocket *ws;
|
|
||||||
} m_client_socket;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Remote IP of the client.
|
* @brief Remote IP of the client.
|
||||||
@ -126,27 +93,6 @@ class NetworkSocket : public QObject
|
|||||||
* @details In the case of the WebSocket we also check if this has been proxy forwarded.
|
* @details In the case of the WebSocket we also check if this has been proxy forwarded.
|
||||||
*/
|
*/
|
||||||
QHostAddress m_socket_ip;
|
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
|
#endif
|
||||||
|
@ -52,6 +52,12 @@ void PacketID::handlePacket(AreaData *area, AOClient &client) const
|
|||||||
client.m_version.release = 2;
|
client.m_version.release = 2;
|
||||||
client.m_version.major = 10;
|
client.m_version.major = 10;
|
||||||
client.m_version.minor = 0;
|
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) {
|
if (client.m_version.release != 2) {
|
||||||
|
125
src/server.cpp
125
src/server.cpp
@ -30,16 +30,11 @@
|
|||||||
#include "network/network_socket.h"
|
#include "network/network_socket.h"
|
||||||
#include "packet/packet_factory.h"
|
#include "packet/packet_factory.h"
|
||||||
|
|
||||||
Server::Server(int p_port, int p_ws_port, QObject *parent) :
|
Server::Server(int p_ws_port, QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
port(p_port),
|
m_port(p_ws_port),
|
||||||
ws_port(p_ws_port),
|
|
||||||
m_player_count(0)
|
m_player_count(0)
|
||||||
{
|
{
|
||||||
server = new QTcpServer(this);
|
|
||||||
|
|
||||||
connect(server, &QTcpServer::newConnection, this, &Server::clientConnected);
|
|
||||||
|
|
||||||
timer = new QTimer(this);
|
timer = new QTimer(this);
|
||||||
|
|
||||||
db_manager = new DBManager;
|
db_manager = new DBManager;
|
||||||
@ -71,24 +66,15 @@ void Server::start()
|
|||||||
if (bind_addr.protocol() != QAbstractSocket::IPv4Protocol && bind_addr.protocol() != QAbstractSocket::IPv6Protocol && bind_addr != QHostAddress::Any) {
|
if (bind_addr.protocol() != QAbstractSocket::IPv4Protocol && bind_addr.protocol() != QAbstractSocket::IPv6Protocol && bind_addr != QHostAddress::Any) {
|
||||||
qDebug() << bind_ip << "is an invalid IP address to listen on! Server not starting, check your config.";
|
qDebug() << bind_ip << "is an invalid IP address to listen on! Server not starting, check your config.";
|
||||||
}
|
}
|
||||||
if (!server->listen(bind_addr, port)) {
|
|
||||||
|
server = new QWebSocketServer("Akashi", QWebSocketServer::NonSecureMode, this);
|
||||||
|
if (!server->listen(bind_addr, m_port)) {
|
||||||
qDebug() << "Server error:" << server->errorString();
|
qDebug() << "Server error:" << server->errorString();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qDebug() << "Server listening on" << port;
|
connect(server, &QWebSocketServer::newConnection,
|
||||||
}
|
this, &Server::clientConnected);
|
||||||
|
qInfo() << "Server listening on" << server->serverPort();
|
||||||
// Enable WebAO
|
|
||||||
if (ConfigManager::webaoEnabled()) {
|
|
||||||
ws_server = new QWebSocketServer("Akashi", QWebSocketServer::NonSecureMode, this);
|
|
||||||
if (!ws_server->listen(bind_addr, ConfigManager::webaoPort())) {
|
|
||||||
qDebug() << "Websocket Server error:" << ws_server->errorString();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
connect(ws_server, &QWebSocketServer::newConnection,
|
|
||||||
this, &Server::ws_clientConnected);
|
|
||||||
qInfo() << "Websocket Server listening on" << ConfigManager::webaoPort();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if any Discord webhooks are enabled.
|
// Checks if any Discord webhooks are enabled.
|
||||||
@ -97,7 +83,7 @@ void Server::start()
|
|||||||
// Construct modern advertiser if enabled in config
|
// Construct modern advertiser if enabled in config
|
||||||
if (ConfigManager::advertiseServer()) {
|
if (ConfigManager::advertiseServer()) {
|
||||||
AdvertiserTimer = new QTimer(this);
|
AdvertiserTimer = new QTimer(this);
|
||||||
ms3_Advertiser = new Advertiser();
|
ms3_Advertiser = new Advertiser(server->serverPort());
|
||||||
|
|
||||||
connect(AdvertiserTimer, &QTimer::timeout, ms3_Advertiser, &Advertiser::msAdvertiseServer);
|
connect(AdvertiserTimer, &QTimer::timeout, ms3_Advertiser, &Advertiser::msAdvertiseServer);
|
||||||
connect(this, &Server::playerCountUpdated, ms3_Advertiser, &Advertiser::updatePlayerCount);
|
connect(this, &Server::playerCountUpdated, ms3_Advertiser, &Advertiser::updatePlayerCount);
|
||||||
@ -161,98 +147,7 @@ QVector<AOClient *> Server::getClients()
|
|||||||
|
|
||||||
void Server::clientConnected()
|
void Server::clientConnected()
|
||||||
{
|
{
|
||||||
QTcpSocket *socket = server->nextPendingConnection();
|
QWebSocket *socket = server->nextPendingConnection();
|
||||||
|
|
||||||
// Too many players. Reject connection!
|
|
||||||
// This also enforces the maximum playercount.
|
|
||||||
if (m_available_ids.empty()) {
|
|
||||||
AOPacket *disconnect_reason = PacketFactory::createPacket("BD", {"Maximum playercount has been reached."});
|
|
||||||
socket->write(disconnect_reason->toUtf8());
|
|
||||||
socket->flush();
|
|
||||||
socket->close();
|
|
||||||
socket->deleteLater();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int user_id = m_available_ids.pop();
|
|
||||||
// The parent hierachry looks like this :
|
|
||||||
// QTcpSocket -> NetworkSocket -> AOClient
|
|
||||||
NetworkSocket *l_socket = new NetworkSocket(socket, socket);
|
|
||||||
AOClient *client = new AOClient(this, l_socket, l_socket, user_id, music_manager);
|
|
||||||
m_clients_ids.insert(user_id, client);
|
|
||||||
m_player_state_observer.registerClient(client);
|
|
||||||
|
|
||||||
int multiclient_count = 1;
|
|
||||||
bool is_at_multiclient_limit = false;
|
|
||||||
client->calculateIpid();
|
|
||||||
auto ban = db_manager->isIPBanned(client->getIpid());
|
|
||||||
bool is_banned = ban.first;
|
|
||||||
for (AOClient *joined_client : qAsConst(m_clients)) {
|
|
||||||
if (client->m_remote_ip.isEqual(joined_client->m_remote_ip))
|
|
||||||
multiclient_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (multiclient_count > ConfigManager::multiClientLimit() && !client->m_remote_ip.isLoopback())
|
|
||||||
is_at_multiclient_limit = true;
|
|
||||||
|
|
||||||
if (is_banned) {
|
|
||||||
QString ban_duration;
|
|
||||||
if (!(ban.second.duration == -2)) {
|
|
||||||
ban_duration = QDateTime::fromSecsSinceEpoch(ban.second.time).addSecs(ban.second.duration).toString("MM/dd/yyyy, hh:mm");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ban_duration = "The heat death of the universe.";
|
|
||||||
}
|
|
||||||
AOPacket *ban_reason = PacketFactory::createPacket("BD", {"Reason: " + ban.second.reason + "\nBan ID: " + QString::number(ban.second.id) + "\nUntil: " + ban_duration});
|
|
||||||
socket->write(ban_reason->toUtf8());
|
|
||||||
}
|
|
||||||
if (is_banned || is_at_multiclient_limit) {
|
|
||||||
socket->flush();
|
|
||||||
client->deleteLater();
|
|
||||||
socket->close();
|
|
||||||
markIDFree(user_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QHostAddress l_remote_ip = client->m_remote_ip;
|
|
||||||
if (l_remote_ip.protocol() == QAbstractSocket::IPv6Protocol) {
|
|
||||||
l_remote_ip = parseToIPv4(l_remote_ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isIPBanned(l_remote_ip)) {
|
|
||||||
QString l_reason = "Your IP has been banned by a moderator.";
|
|
||||||
AOPacket *l_ban_reason = PacketFactory::createPacket("BD", {l_reason});
|
|
||||||
socket->write(l_ban_reason->toUtf8());
|
|
||||||
client->deleteLater();
|
|
||||||
socket->close();
|
|
||||||
markIDFree(user_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_clients.append(client);
|
|
||||||
connect(l_socket, &NetworkSocket::clientDisconnected, this, [=] {
|
|
||||||
if (client->hasJoined()) {
|
|
||||||
decreasePlayerCount();
|
|
||||||
}
|
|
||||||
m_clients.removeAll(client);
|
|
||||||
client->deleteLater();
|
|
||||||
});
|
|
||||||
connect(l_socket, &NetworkSocket::handlePacket, client, &AOClient::handlePacket);
|
|
||||||
|
|
||||||
// This is the infamous workaround for
|
|
||||||
// tsuserver4. It should disable fantacrypt
|
|
||||||
// completely in any client 2.4.3 or newer
|
|
||||||
AOPacket *decryptor = PacketFactory::createPacket("decryptor", {"NOENCRYPT"});
|
|
||||||
client->sendPacket(decryptor);
|
|
||||||
hookupAOClient(client);
|
|
||||||
#ifdef NET_DEBUG
|
|
||||||
qDebug() << client->m_remote_ip.toString() << "connected";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::ws_clientConnected()
|
|
||||||
{
|
|
||||||
QWebSocket *socket = ws_server->nextPendingConnection();
|
|
||||||
NetworkSocket *l_socket = new NetworkSocket(socket, socket);
|
NetworkSocket *l_socket = new NetworkSocket(socket, socket);
|
||||||
|
|
||||||
// Too many players. Reject connection!
|
// Too many players. Reject connection!
|
||||||
|
40
src/server.h
40
src/server.h
@ -25,8 +25,6 @@
|
|||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QStack>
|
#include <QStack>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QTcpServer>
|
|
||||||
#include <QTcpSocket>
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QWebSocket>
|
#include <QWebSocket>
|
||||||
#include <QWebSocketServer>
|
#include <QWebSocketServer>
|
||||||
@ -44,7 +42,6 @@ class DBManager;
|
|||||||
class Discord;
|
class Discord;
|
||||||
class MusicManager;
|
class MusicManager;
|
||||||
class ULogger;
|
class ULogger;
|
||||||
class WSProxy;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The class that represents the actual server as it is.
|
* @brief The class that represents the actual server as it is.
|
||||||
@ -57,11 +54,10 @@ class Server : public QObject
|
|||||||
/**
|
/**
|
||||||
* @brief Creates a Server instance.
|
* @brief Creates a Server instance.
|
||||||
*
|
*
|
||||||
* @param p_port The TCP port to listen for connections on.
|
* @param p_ws_port The port to listen for connections on.
|
||||||
* @param p_ws_port The WebSocket port to listen for connections on.
|
|
||||||
* @param parent Qt-based parent, passed along to inherited constructor from QObject.
|
* @param parent Qt-based parent, passed along to inherited constructor from QObject.
|
||||||
*/
|
*/
|
||||||
Server(int p_port, int p_ws_port, QObject *parent = nullptr);
|
Server(int p_ws_port, QObject *parent = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destructor for the Server class.
|
* @brief Destructor for the Server class.
|
||||||
@ -73,8 +69,7 @@ class Server : public QObject
|
|||||||
/**
|
/**
|
||||||
* @brief Starts the server.
|
* @brief Starts the server.
|
||||||
*
|
*
|
||||||
* @details Amongst other things, this function starts the listening on the given TCP port, sets up the server
|
* @details Starts listening for incoming connections on the given port.
|
||||||
* according to the configuration file, and starts listening on the WebSocket port if it is not `-1`.
|
|
||||||
*
|
*
|
||||||
* Advertising is not done here -- see Advertiser::contactMasterServer() for that.
|
* Advertising is not done here -- see Advertiser::contactMasterServer() for that.
|
||||||
*/
|
*/
|
||||||
@ -349,14 +344,6 @@ class Server : public QObject
|
|||||||
*/
|
*/
|
||||||
void clientConnected();
|
void clientConnected();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Handles a new connection.
|
|
||||||
*
|
|
||||||
* @details The function creates an AOClient to represent the user, assigns a user ID to them, and
|
|
||||||
* checks if the client is banned.
|
|
||||||
*/
|
|
||||||
void ws_clientConnected();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Method to construct and reconstruct Discord Webhook Integration.
|
* @brief Method to construct and reconstruct Discord Webhook Integration.
|
||||||
*
|
*
|
||||||
@ -421,22 +408,10 @@ class Server : public QObject
|
|||||||
void logConnectionAttempt(const QString &f_ip_address, const QString &f_ipid, const QString &f_hwid);
|
void logConnectionAttempt(const QString &f_ip_address, const QString &f_ipid, const QString &f_hwid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
|
||||||
* @brief The proxy used for WebSocket connections.
|
|
||||||
*
|
|
||||||
* @see WSProxy and WSClient for an explanation as to why this is a thing.
|
|
||||||
*/
|
|
||||||
WSProxy *proxy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Listens for incoming TCP connections.
|
|
||||||
*/
|
|
||||||
QTcpServer *server;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Listens for incoming websocket connections.
|
* @brief Listens for incoming websocket connections.
|
||||||
*/
|
*/
|
||||||
QWebSocketServer *ws_server;
|
QWebSocketServer *server;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Handles Discord webhooks.
|
* @brief Handles Discord webhooks.
|
||||||
@ -463,15 +438,10 @@ class Server : public QObject
|
|||||||
*/
|
*/
|
||||||
MusicManager *music_manager;
|
MusicManager *music_manager;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The port through which the server will accept TCP connections.
|
|
||||||
*/
|
|
||||||
int port;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The port through which the server will accept WebSocket connections.
|
* @brief The port through which the server will accept WebSocket connections.
|
||||||
*/
|
*/
|
||||||
int ws_port;
|
int m_port;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The collection of all currently connected clients.
|
* @brief The collection of all currently connected clients.
|
||||||
|
@ -58,8 +58,6 @@ class tst_ConfigManager : public QObject
|
|||||||
|
|
||||||
void webaoEnabled();
|
void webaoEnabled();
|
||||||
|
|
||||||
void webaoPort();
|
|
||||||
|
|
||||||
void authType();
|
void authType();
|
||||||
|
|
||||||
void modpass();
|
void modpass();
|
||||||
@ -284,10 +282,6 @@ void tst_ConfigManager::webaoEnabled()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_ConfigManager::webaoPort()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void tst_ConfigManager::authType()
|
void tst_ConfigManager::authType()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user