1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-22 22:13:35 +02:00

Simplified networking API

This commit is contained in:
Ivan Savenko 2024-01-12 16:55:36 +02:00
parent 9fb7d2817a
commit 709905b1a0
12 changed files with 62 additions and 142 deletions

View File

@ -138,9 +138,8 @@ CServerHandler::~CServerHandler()
CServerHandler::CServerHandler()
: state(EClientState::NONE)
, networkHandler(INetworkHandler::createHandler())
, networkClient(networkHandler->createClientTCP(*this))
, applier(std::make_unique<CApplier<CBaseForLobbyApply>>())
, lobbyClient(std::make_unique<GlobalLobbyClient>(networkHandler))
, lobbyClient(std::make_unique<GlobalLobbyClient>())
, 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<INetworkConnection> & netConnection)
{
networkConnection = netConnection;
logNetwork->info("Connection established");
c = std::make_shared<CConnection>(netConnection);
c->uuid = uuid;
@ -868,8 +869,11 @@ void CServerHandler::onPacketReceived(const std::shared_ptr<INetworkConnection>
}
}
void CServerHandler::onDisconnected(const std::shared_ptr<INetworkConnection> &)
void CServerHandler::onDisconnected(const std::shared_ptr<INetworkConnection> & connection)
{
assert(networkConnection == connection);
networkConnection.reset();
if(state == EClientState::DISCONNECTING)
{
logNetwork->info("Successfully closed connection to server, ending listening thread!");

View File

@ -86,8 +86,7 @@ class CServerHandler : public IServerAPI, public LobbyInfo, public INetworkClien
{
friend class ApplyOnLobbyHandlerNetPackVisitor;
std::unique_ptr<INetworkHandler> networkHandler;
std::unique_ptr<INetworkClient> networkClient;
std::shared_ptr<INetworkConnection> networkConnection;
std::unique_ptr<GlobalLobbyClient> lobbyClient;
std::unique_ptr<CApplier<CBaseForLobbyApply>> applier;
std::shared_ptr<CMapInfo> mapToStart;
@ -113,6 +112,8 @@ class CServerHandler : public IServerAPI, public LobbyInfo, public INetworkClien
bool isServerLocal() const;
public:
std::unique_ptr<INetworkHandler> networkHandler;
std::shared_ptr<CConnection> c;
std::atomic<EClientState> state;

View File

@ -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<INetworkHandler> & 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<INetworkConnection> &)
void GlobalLobbyClient::onConnectionEstablished(const std::shared_ptr<INetworkConnection> & 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<INetworkConnection> &)
void GlobalLobbyClient::onDisconnected(const std::shared_ptr<INetworkConnection> & 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<uint8_t> 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<GlobalLobbyLoginWindow> GlobalLobbyClient::createLoginWindow()

View File

@ -20,7 +20,7 @@ class GlobalLobbyWindow;
class GlobalLobbyClient : public INetworkClientListener, boost::noncopyable
{
std::unique_ptr<INetworkClient> networkClient;
std::shared_ptr<INetworkConnection> networkConnection;
std::weak_ptr<GlobalLobbyLoginWindow> loginWindow;
std::weak_ptr<GlobalLobbyWindow> lobbyWindow;
@ -42,7 +42,7 @@ class GlobalLobbyClient : public INetworkClientListener, boost::noncopyable
void receiveActiveAccounts(const JsonNode & json);
public:
explicit GlobalLobbyClient(const std::unique_ptr<INetworkHandler> & handler);
explicit GlobalLobbyClient();
~GlobalLobbyClient();
void sendMessage(const JsonNode & data);

View File

@ -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

View File

@ -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<NetworkContext> & context)
: io(context)
, socket(std::make_shared<NetworkSocket>(*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<NetworkConnection>(*this, socket);
connection->start();
listener.onConnectionEstablished(connection);
}
bool NetworkClient::isConnected() const
{
return connection != nullptr;
}
void NetworkClient::sendPacket(const std::vector<uint8_t> & message)
{
connection->sendPacket(message);
}
void NetworkClient::onDisconnected(const std::shared_ptr<INetworkConnection> & connection)
{
this->connection.reset();
listener.onDisconnected(connection);
}
void NetworkClient::onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message)
{
listener.onPacketReceived(connection, message);
}
VCMI_LIB_NAMESPACE_END

View File

@ -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<NetworkContext> io;
std::shared_ptr<NetworkSocket> socket;
std::shared_ptr<NetworkConnection> connection;
INetworkClientListener & listener;
void onConnected(const boost::system::error_code & ec);
void onDisconnected(const std::shared_ptr<INetworkConnection> & connection) override;
void onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message) override;
public:
NetworkClient(INetworkClientListener & listener, const std::shared_ptr<NetworkContext> & context);
bool isConnected() const override;
void sendPacket(const std::vector<uint8_t> & message) override;
void start(const std::string & host, uint16_t port) override;
};
VCMI_LIB_NAMESPACE_END

View File

@ -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<INetworkServer> NetworkHandler::createServerTCP(INetworkServerLi
return std::make_unique<NetworkServer>(listener, io);
}
std::unique_ptr<INetworkClient> NetworkHandler::createClientTCP(INetworkClientListener & listener)
void NetworkHandler::connectToRemote(INetworkClientListener & listener, const std::string & host, uint16_t port)
{
return std::make_unique<NetworkClient>(listener, io);
auto socket = std::make_shared<NetworkSocket>(*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<NetworkConnection>(listener, socket);
connection->start();
listener.onConnectionEstablished(connection);
});
}
void NetworkHandler::run()

View File

@ -21,7 +21,7 @@ public:
NetworkHandler();
std::unique_ptr<INetworkServer> createServerTCP(INetworkServerListener & listener) override;
std::unique_ptr<INetworkClient> 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;

View File

@ -30,7 +30,6 @@ public:
virtual bool isConnected() const = 0;
virtual void sendPacket(const std::vector<uint8_t> & 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<INetworkServer> 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<INetworkClient> 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

View File

@ -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_ptr<INetworkConnec
if(json["type"].String() == "loginSuccess")
return receiveLoginSuccess(json);
if(json["type"].String() == "accountJoinsRoom")
return receiveAccountJoinsRoom(json);
throw std::runtime_error("Received unexpected message from lobby server: " + json["type"].String());
}
@ -52,13 +54,19 @@ void GlobalLobbyProcessor::receiveLoginSuccess(const JsonNode & json)
logGlobal->info("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<INetworkConnection> &)
void GlobalLobbyProcessor::onConnectionEstablished(const std::shared_ptr<INetworkConnection> & connection)
{
controlConnection = connection;
logGlobal->info("Connection to lobby server established");
JsonNode toSend;
@ -78,5 +86,5 @@ void GlobalLobbyProcessor::sendMessage(const JsonNode & data)
std::vector<uint8_t> payloadBuffer(payloadBegin, payloadEnd);
networkClient->sendPacket(payloadBuffer);
controlConnection->sendPacket(payloadBuffer);
}

View File

@ -23,7 +23,6 @@ class GlobalLobbyProcessor : public INetworkClientListener
std::shared_ptr<INetworkConnection> controlConnection;
// std::set<std::shared_ptr<INetworkConnection>> proxyConnections;
std::unique_ptr<INetworkClient> networkClient;
void onDisconnected(const std::shared_ptr<INetworkConnection> & connection) override;
void onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & 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);
};