diff options
Diffstat (limited to 'src/net')
| -rw-r--r-- | src/net/netconnection.cpp | 5 | ||||
| -rw-r--r-- | src/net/netconnection.h | 28 | ||||
| -rw-r--r-- | src/net/nettcpconnection.cpp | 102 | ||||
| -rw-r--r-- | src/net/nettcpconnection.h | 31 | ||||
| -rw-r--r-- | src/net/netwebsocketconnection.cpp | 97 | ||||
| -rw-r--r-- | src/net/netwebsocketconnection.h | 32 |
6 files changed, 295 insertions, 0 deletions
diff --git a/src/net/netconnection.cpp b/src/net/netconnection.cpp new file mode 100644 index 00000000..63ca7060 --- /dev/null +++ b/src/net/netconnection.cpp @@ -0,0 +1,5 @@ +#include "netconnection.h" + +NetConnection::NetConnection(QObject *parent) + : QObject(parent) +{} diff --git a/src/net/netconnection.h b/src/net/netconnection.h new file mode 100644 index 00000000..0b5d6be3 --- /dev/null +++ b/src/net/netconnection.h @@ -0,0 +1,28 @@ +#pragma once + +#include "aopacket.h" +#include "datatypes.h" + +#include <QObject> + +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 new file mode 100644 index 00000000..2bc52b71 --- /dev/null +++ b/src/net/nettcpconnection.cpp @@ -0,0 +1,102 @@ +#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<QAbstractSocket::SocketError>::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 new file mode 100644 index 00000000..40dae196 --- /dev/null +++ b/src/net/nettcpconnection.h @@ -0,0 +1,31 @@ +#pragma once + +#include "aopacket.h" +#include "datatypes.h" +#include "netconnection.h" + +#include <QTcpSocket> + +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.cpp b/src/net/netwebsocketconnection.cpp new file mode 100644 index 00000000..a9d2e10c --- /dev/null +++ b/src/net/netwebsocketconnection.cpp @@ -0,0 +1,97 @@ +#include "netwebsocketconnection.h" + +#include "networkmanager.h" + +#include <QNetworkRequest> +#include <QUrl> + +NetWebSocketConnection::NetWebSocketConnection(NetworkManager *networkManager) + : NetConnection(networkManager) + , m_network_manager(networkManager) + , m_socket(new QWebSocket(QString(), QWebSocketProtocol::VersionLatest, this)) + , m_last_state(QAbstractSocket::UnconnectedState) +{ + connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error), this, &NetWebSocketConnection::onError); + connect(m_socket, &QWebSocket::stateChanged, this, &NetWebSocketConnection::onStateChanged); + connect(m_socket, &QWebSocket::textMessageReceived, this, &NetWebSocketConnection::onTextMessageReceived); +} + +NetWebSocketConnection::~NetWebSocketConnection() +{ + m_socket->disconnect(this); + disconnectFromServer(); +} + +bool NetWebSocketConnection::isConnected() +{ + return m_last_state == QAbstractSocket::ConnectedState; +} + +void NetWebSocketConnection::connectToServer(ServerInfo &server) +{ + disconnectFromServer(); + + QUrl url; + url.setScheme("ws"); + url.setHost(server.ip); + url.setPort(server.port); + + QNetworkRequest req(url); + req.setHeader(QNetworkRequest::UserAgentHeader, m_network_manager->get_user_agent()); + + m_socket->open(req); +} + +void NetWebSocketConnection::disconnectFromServer() +{ + if (isConnected()) + { + m_socket->close(QWebSocketProtocol::CloseCodeGoingAway); + } +} + +void NetWebSocketConnection::sendPacket(AOPacket packet) +{ + m_socket->sendTextMessage(packet.toString(true)); +} + +void NetWebSocketConnection::onError() +{ + Q_EMIT errorOccurred(m_socket->errorString()); +} + +void NetWebSocketConnection::onStateChanged(QAbstractSocket::SocketState state) +{ + m_last_state = state; + switch (state) + { + default: + break; + + case QAbstractSocket::ConnectedState: + Q_EMIT connectedToServer(); + break; + + case QAbstractSocket::UnconnectedState: + Q_EMIT disconnectFromServer(); + break; + } +} + +void NetWebSocketConnection::onTextMessageReceived(QString message) +{ + if (!message.endsWith("#%")) + { + return; + } + message.chop(2); + + QStringList raw_content = message.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/netwebsocketconnection.h b/src/net/netwebsocketconnection.h new file mode 100644 index 00000000..26f41a6e --- /dev/null +++ b/src/net/netwebsocketconnection.h @@ -0,0 +1,32 @@ +#pragma once + +#include "netconnection.h" + +class NetworkManager; + +#include <QWebSocket> + +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); +}; |
