From 709905b1a0087d8ad48d24b7c2fcd4bc645522a8 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 12 Jan 2024 16:55:36 +0200 Subject: [PATCH] Simplified networking API --- client/CServerHandler.cpp | 14 +++-- client/CServerHandler.h | 5 +- client/globalLobby/GlobalLobbyClient.cpp | 21 ++++--- client/globalLobby/GlobalLobbyClient.h | 4 +- cmake_modules/VCMI_lib.cmake | 2 - lib/network/NetworkClient.cpp | 70 ------------------------ lib/network/NetworkClient.h | 41 -------------- lib/network/NetworkHandler.cpp | 20 ++++++- lib/network/NetworkHandler.h | 2 +- lib/network/NetworkInterface.h | 7 ++- server/GlobalLobbyProcessor.cpp | 16 ++++-- server/GlobalLobbyProcessor.h | 2 +- 12 files changed, 62 insertions(+), 142 deletions(-) delete mode 100644 lib/network/NetworkClient.cpp delete mode 100644 lib/network/NetworkClient.h diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index a592ba61d..f6ce8a5c4 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -138,9 +138,8 @@ CServerHandler::~CServerHandler() CServerHandler::CServerHandler() : state(EClientState::NONE) , networkHandler(INetworkHandler::createHandler()) - , networkClient(networkHandler->createClientTCP(*this)) , applier(std::make_unique>()) - , lobbyClient(std::make_unique(networkHandler)) + , lobbyClient(std::make_unique()) , client(nullptr) , loadMode(0) , campaignStateToSend(nullptr) @@ -268,7 +267,7 @@ void CServerHandler::connectToServer(const std::string & addr, const ui16 port) serverPort->Integer() = port; } - networkClient->start(addr, port); + networkHandler->connectToRemote(*this, addr, port); } void CServerHandler::onConnectionFailed(const std::string & errorMessage) @@ -296,11 +295,13 @@ void CServerHandler::onTimer() } assert(isServerLocal()); - networkClient->start(getLocalHostname(), getLocalPort()); + networkHandler->connectToRemote(*this, getLocalHostname(), getLocalPort()); } void CServerHandler::onConnectionEstablished(const std::shared_ptr & netConnection) { + networkConnection = netConnection; + logNetwork->info("Connection established"); c = std::make_shared(netConnection); c->uuid = uuid; @@ -868,8 +869,11 @@ void CServerHandler::onPacketReceived(const std::shared_ptr } } -void CServerHandler::onDisconnected(const std::shared_ptr &) +void CServerHandler::onDisconnected(const std::shared_ptr & connection) { + assert(networkConnection == connection); + networkConnection.reset(); + if(state == EClientState::DISCONNECTING) { logNetwork->info("Successfully closed connection to server, ending listening thread!"); diff --git a/client/CServerHandler.h b/client/CServerHandler.h index 7b761d2cc..0a5999c0e 100644 --- a/client/CServerHandler.h +++ b/client/CServerHandler.h @@ -86,8 +86,7 @@ class CServerHandler : public IServerAPI, public LobbyInfo, public INetworkClien { friend class ApplyOnLobbyHandlerNetPackVisitor; - std::unique_ptr networkHandler; - std::unique_ptr networkClient; + std::shared_ptr networkConnection; std::unique_ptr lobbyClient; std::unique_ptr> applier; std::shared_ptr mapToStart; @@ -113,6 +112,8 @@ class CServerHandler : public IServerAPI, public LobbyInfo, public INetworkClien bool isServerLocal() const; public: + std::unique_ptr networkHandler; + std::shared_ptr c; std::atomic state; diff --git a/client/globalLobby/GlobalLobbyClient.cpp b/client/globalLobby/GlobalLobbyClient.cpp index 491d8f4e1..66877ef82 100644 --- a/client/globalLobby/GlobalLobbyClient.cpp +++ b/client/globalLobby/GlobalLobbyClient.cpp @@ -17,17 +17,15 @@ #include "../gui/CGuiHandler.h" #include "../gui/WindowHandler.h" #include "../windows/InfoWindows.h" +#include "../CServerHandler.h" #include "../../lib/CConfigHandler.h" #include "../../lib/MetaString.h" #include "../../lib/TextOperations.h" +GlobalLobbyClient::GlobalLobbyClient() = default; GlobalLobbyClient::~GlobalLobbyClient() = default; -GlobalLobbyClient::GlobalLobbyClient(const std::unique_ptr & handler) - : networkClient(handler->createClientTCP(*this)) -{} - static std::string getCurrentTimeFormatted(int timeOffsetSeconds = 0) { // FIXME: better/unified way to format date @@ -149,8 +147,10 @@ void GlobalLobbyClient::receiveActiveAccounts(const JsonNode & json) //} } -void GlobalLobbyClient::onConnectionEstablished(const std::shared_ptr &) +void GlobalLobbyClient::onConnectionEstablished(const std::shared_ptr & connection) { + networkConnection = connection; + JsonNode toSend; std::string accountID = settings["lobby"]["accountID"].String(); @@ -189,8 +189,11 @@ void GlobalLobbyClient::onConnectionFailed(const std::string & errorMessage) loginWindowPtr->onConnectionFailed(errorMessage); } -void GlobalLobbyClient::onDisconnected(const std::shared_ptr &) +void GlobalLobbyClient::onDisconnected(const std::shared_ptr & connection) { + assert(connection == networkConnection); + networkConnection.reset(); + GH.windows().popWindows(1); CInfoWindow::showInfoDialog("Connection to game lobby was lost!", {}); } @@ -205,19 +208,19 @@ void GlobalLobbyClient::sendMessage(const JsonNode & data) std::vector payloadBuffer(payloadBegin, payloadEnd); - networkClient->sendPacket(payloadBuffer); + networkConnection->sendPacket(payloadBuffer); } void GlobalLobbyClient::connect() { std::string hostname = settings["lobby"]["hostname"].String(); int16_t port = settings["lobby"]["port"].Integer(); - networkClient->start(hostname, port); + CSH->networkHandler->connectToRemote(*this, hostname, port); } bool GlobalLobbyClient::isConnected() { - return networkClient->isConnected(); + return networkConnection != nullptr; } std::shared_ptr GlobalLobbyClient::createLoginWindow() diff --git a/client/globalLobby/GlobalLobbyClient.h b/client/globalLobby/GlobalLobbyClient.h index 92569c3dd..ca54c0535 100644 --- a/client/globalLobby/GlobalLobbyClient.h +++ b/client/globalLobby/GlobalLobbyClient.h @@ -20,7 +20,7 @@ class GlobalLobbyWindow; class GlobalLobbyClient : public INetworkClientListener, boost::noncopyable { - std::unique_ptr networkClient; + std::shared_ptr networkConnection; std::weak_ptr loginWindow; std::weak_ptr lobbyWindow; @@ -42,7 +42,7 @@ class GlobalLobbyClient : public INetworkClientListener, boost::noncopyable void receiveActiveAccounts(const JsonNode & json); public: - explicit GlobalLobbyClient(const std::unique_ptr & handler); + explicit GlobalLobbyClient(); ~GlobalLobbyClient(); void sendMessage(const JsonNode & data); diff --git a/cmake_modules/VCMI_lib.cmake b/cmake_modules/VCMI_lib.cmake index 65549110c..e76542a87 100644 --- a/cmake_modules/VCMI_lib.cmake +++ b/cmake_modules/VCMI_lib.cmake @@ -124,7 +124,6 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) ${MAIN_LIB_DIR}/modding/IdentifierStorage.cpp ${MAIN_LIB_DIR}/modding/ModUtility.cpp - ${MAIN_LIB_DIR}/network/NetworkClient.cpp ${MAIN_LIB_DIR}/network/NetworkConnection.cpp ${MAIN_LIB_DIR}/network/NetworkHandler.cpp ${MAIN_LIB_DIR}/network/NetworkServer.cpp @@ -476,7 +475,6 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) ${MAIN_LIB_DIR}/modding/ModUtility.h ${MAIN_LIB_DIR}/modding/ModVerificationInfo.h - ${MAIN_LIB_DIR}/network/NetworkClient.h ${MAIN_LIB_DIR}/network/NetworkConnection.h ${MAIN_LIB_DIR}/network/NetworkDefines.h ${MAIN_LIB_DIR}/network/NetworkHandler.h diff --git a/lib/network/NetworkClient.cpp b/lib/network/NetworkClient.cpp deleted file mode 100644 index 888660b3d..000000000 --- a/lib/network/NetworkClient.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * NetworkClient.cpp, part of VCMI engine - * - * Authors: listed in file AUTHORS in main folder - * - * License: GNU General Public License v2.0 or later - * Full text of license available in license.txt file, in main folder - * - */ -#include "StdInc.h" -#include "NetworkClient.h" -#include "NetworkConnection.h" - -VCMI_LIB_NAMESPACE_BEGIN - -NetworkClient::NetworkClient(INetworkClientListener & listener, const std::shared_ptr & context) - : io(context) - , socket(std::make_shared(*context)) - , listener(listener) -{ -} - -void NetworkClient::start(const std::string & host, uint16_t port) -{ - if (isConnected()) - throw std::runtime_error("Attempting to connect while already connected!"); - - boost::asio::ip::tcp::resolver resolver(*io); - auto endpoints = resolver.resolve(host, std::to_string(port)); - - boost::asio::async_connect(*socket, endpoints, std::bind(&NetworkClient::onConnected, this, _1)); -} - -void NetworkClient::onConnected(const boost::system::error_code & ec) -{ - if (ec) - { - listener.onConnectionFailed(ec.message()); - return; - } - - connection = std::make_shared(*this, socket); - connection->start(); - - listener.onConnectionEstablished(connection); -} - -bool NetworkClient::isConnected() const -{ - return connection != nullptr; -} - -void NetworkClient::sendPacket(const std::vector & message) -{ - connection->sendPacket(message); -} - -void NetworkClient::onDisconnected(const std::shared_ptr & connection) -{ - this->connection.reset(); - listener.onDisconnected(connection); -} - -void NetworkClient::onPacketReceived(const std::shared_ptr & connection, const std::vector & message) -{ - listener.onPacketReceived(connection, message); -} - - -VCMI_LIB_NAMESPACE_END diff --git a/lib/network/NetworkClient.h b/lib/network/NetworkClient.h deleted file mode 100644 index 301d3d00d..000000000 --- a/lib/network/NetworkClient.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * NetworkClient.h, part of VCMI engine - * - * Authors: listed in file AUTHORS in main folder - * - * License: GNU General Public License v2.0 or later - * Full text of license available in license.txt file, in main folder - * - */ -#pragma once - -#include "NetworkDefines.h" - -VCMI_LIB_NAMESPACE_BEGIN - -class NetworkConnection; - -class NetworkClient : public INetworkConnectionListener, public INetworkClient -{ - std::shared_ptr io; - std::shared_ptr socket; - std::shared_ptr connection; - - INetworkClientListener & listener; - - void onConnected(const boost::system::error_code & ec); - - void onDisconnected(const std::shared_ptr & connection) override; - void onPacketReceived(const std::shared_ptr & connection, const std::vector & message) override; - -public: - NetworkClient(INetworkClientListener & listener, const std::shared_ptr & context); - - bool isConnected() const override; - - void sendPacket(const std::vector & message) override; - - void start(const std::string & host, uint16_t port) override; -}; - -VCMI_LIB_NAMESPACE_END diff --git a/lib/network/NetworkHandler.cpp b/lib/network/NetworkHandler.cpp index ed5503f73..ddb15e091 100644 --- a/lib/network/NetworkHandler.cpp +++ b/lib/network/NetworkHandler.cpp @@ -10,8 +10,8 @@ #include "StdInc.h" #include "NetworkHandler.h" -#include "NetworkClient.h" #include "NetworkServer.h" +#include "NetworkConnection.h" VCMI_LIB_NAMESPACE_BEGIN @@ -29,9 +29,23 @@ std::unique_ptr NetworkHandler::createServerTCP(INetworkServerLi return std::make_unique(listener, io); } -std::unique_ptr NetworkHandler::createClientTCP(INetworkClientListener & listener) +void NetworkHandler::connectToRemote(INetworkClientListener & listener, const std::string & host, uint16_t port) { - return std::make_unique(listener, io); + auto socket = std::make_shared(*io); + boost::asio::ip::tcp::resolver resolver(*io); + auto endpoints = resolver.resolve(host, std::to_string(port)); + boost::asio::async_connect(*socket, endpoints, [socket, &listener](const boost::system::error_code& error, const boost::asio::ip::tcp::endpoint& endpoint) + { + if (error) + { + listener.onConnectionFailed(error.message()); + return; + } + auto connection = std::make_shared(listener, socket); + connection->start(); + + listener.onConnectionEstablished(connection); + }); } void NetworkHandler::run() diff --git a/lib/network/NetworkHandler.h b/lib/network/NetworkHandler.h index d41933869..c5b326c67 100644 --- a/lib/network/NetworkHandler.h +++ b/lib/network/NetworkHandler.h @@ -21,7 +21,7 @@ public: NetworkHandler(); std::unique_ptr createServerTCP(INetworkServerListener & listener) override; - std::unique_ptr createClientTCP(INetworkClientListener & listener) override; + void connectToRemote(INetworkClientListener & listener, const std::string & host, uint16_t port) override; void createTimer(INetworkTimerListener & listener, std::chrono::milliseconds duration) override; void run() override; diff --git a/lib/network/NetworkInterface.h b/lib/network/NetworkInterface.h index 4d3072992..3fb98006f 100644 --- a/lib/network/NetworkInterface.h +++ b/lib/network/NetworkInterface.h @@ -30,7 +30,6 @@ public: virtual bool isConnected() const = 0; virtual void sendPacket(const std::vector & message) = 0; - virtual void start(const std::string & host, uint16_t port) = 0; }; /// Base class for incoming connections support @@ -91,9 +90,13 @@ public: virtual std::unique_ptr createServerTCP(INetworkServerListener & listener) = 0; /// Creates an instance of TCP client that allows to establish single outgoing connection to a remote port - virtual std::unique_ptr createClientTCP(INetworkClientListener & listener) = 0; + /// On success: INetworkTimerListener::onConnectionEstablished() will be called, established connection provided as parameter + /// On failure: INetworkTimerListener::onConnectionFailed will be called with human-readable error message + virtual void connectToRemote(INetworkClientListener & listener, const std::string & host, uint16_t port) = 0; /// Creates a timer that will be called once, after specified interval has passed + /// On success: INetworkTimerListener::onTimer() will be called + /// On failure: no-op virtual void createTimer(INetworkTimerListener & listener, std::chrono::milliseconds duration) = 0; /// Starts network processing on this thread. Does not returns until networking processing has been terminated diff --git a/server/GlobalLobbyProcessor.cpp b/server/GlobalLobbyProcessor.cpp index 5138f1b61..33c7a959d 100644 --- a/server/GlobalLobbyProcessor.cpp +++ b/server/GlobalLobbyProcessor.cpp @@ -15,11 +15,10 @@ GlobalLobbyProcessor::GlobalLobbyProcessor(CVCMIServer & owner) : owner(owner) - , networkClient(owner.networkHandler->createClientTCP(*this)) { std::string hostname = settings["lobby"]["hostname"].String(); int16_t port = settings["lobby"]["port"].Integer(); - networkClient->start(hostname, port); + owner.networkHandler->connectToRemote(*this, hostname, port); logGlobal->info("Connecting to lobby server"); } @@ -38,6 +37,9 @@ void GlobalLobbyProcessor::onPacketReceived(const std::shared_ptrinfo("Succesfully connected to lobby server"); } +void GlobalLobbyProcessor::receiveAccountJoinsRoom(const JsonNode & json) +{ + // TODO: establish new connection to lobby, login, and transfer connection to our owner +} + void GlobalLobbyProcessor::onConnectionFailed(const std::string & errorMessage) { throw std::runtime_error("Failed to connect to a lobby server!"); } -void GlobalLobbyProcessor::onConnectionEstablished(const std::shared_ptr &) +void GlobalLobbyProcessor::onConnectionEstablished(const std::shared_ptr & connection) { + controlConnection = connection; logGlobal->info("Connection to lobby server established"); JsonNode toSend; @@ -78,5 +86,5 @@ void GlobalLobbyProcessor::sendMessage(const JsonNode & data) std::vector payloadBuffer(payloadBegin, payloadEnd); - networkClient->sendPacket(payloadBuffer); + controlConnection->sendPacket(payloadBuffer); } diff --git a/server/GlobalLobbyProcessor.h b/server/GlobalLobbyProcessor.h index 530e59161..b6e24fb36 100644 --- a/server/GlobalLobbyProcessor.h +++ b/server/GlobalLobbyProcessor.h @@ -23,7 +23,6 @@ class GlobalLobbyProcessor : public INetworkClientListener std::shared_ptr controlConnection; // std::set> proxyConnections; - std::unique_ptr networkClient; void onDisconnected(const std::shared_ptr & connection) override; void onPacketReceived(const std::shared_ptr & connection, const std::vector & message) override; @@ -34,6 +33,7 @@ class GlobalLobbyProcessor : public INetworkClientListener void receiveLoginFailed(const JsonNode & json); void receiveLoginSuccess(const JsonNode & json); + void receiveAccountJoinsRoom(const JsonNode & json); public: GlobalLobbyProcessor(CVCMIServer & owner); };