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

Finalized new TCP networking API

This commit is contained in:
Ivan Savenko 2024-01-12 01:10:41 +02:00
parent 476a05fed3
commit 80e960bc8e
23 changed files with 306 additions and 241 deletions

View File

@ -46,7 +46,6 @@
#include "../lib/mapping/CMapInfo.h"
#include "../lib/mapObjects/MiscObjects.h"
#include "../lib/modding/ModIncompatibility.h"
#include "../lib/network/NetworkClient.h"
#include "../lib/rmg/CMapGenOptions.h"
#include "../lib/serializer/Connection.h"
#include "../lib/filesystem/Filesystem.h"
@ -132,15 +131,16 @@ static const std::string NAME = GameConstants::VCMI_VERSION + std::string(" (")
CServerHandler::~CServerHandler()
{
networkClient->stop();
networkHandler->stop();
threadNetwork->join();
}
CServerHandler::CServerHandler()
: state(EClientState::NONE)
, networkClient(std::make_unique<NetworkClient>(*this))
, networkHandler(INetworkHandler::createHandler())
, networkClient(networkHandler->createClientTCP(*this))
, applier(std::make_unique<CApplier<CBaseForLobbyApply>>())
, lobbyClient(std::make_unique<GlobalLobbyClient>())
, lobbyClient(std::make_unique<GlobalLobbyClient>(networkHandler))
, client(nullptr)
, loadMode(0)
, campaignStateToSend(nullptr)
@ -155,7 +155,7 @@ void CServerHandler::threadRunNetwork()
{
logGlobal->info("Starting network thread");
setThreadName("runNetwork");
networkClient->run();
networkHandler->run();
logGlobal->info("Ending network thread");
}
@ -277,7 +277,7 @@ void CServerHandler::onConnectionFailed(const std::string & errorMessage)
{
// retry - local server might be still starting up
logNetwork->debug("\nCannot establish connection. %s. Retrying...", errorMessage);
networkClient->setTimer(std::chrono::milliseconds(100));
networkHandler->createTimer(*this, std::chrono::milliseconds(100));
}
else
{
@ -299,7 +299,7 @@ void CServerHandler::onTimer()
networkClient->start(getLocalHostname(), getLocalPort());
}
void CServerHandler::onConnectionEstablished(const std::shared_ptr<NetworkConnection> & netConnection)
void CServerHandler::onConnectionEstablished(const std::shared_ptr<INetworkConnection> & netConnection)
{
logNetwork->info("Connection established");
c = std::make_shared<CConnection>(netConnection);
@ -852,7 +852,7 @@ public:
}
};
void CServerHandler::onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message)
void CServerHandler::onPacketReceived(const std::shared_ptr<INetworkConnection> &, const std::vector<uint8_t> & message)
{
CPack * pack = c->retrievePack(message);
if(state == EClientState::DISCONNECTING)
@ -868,7 +868,7 @@ void CServerHandler::onPacketReceived(const std::shared_ptr<NetworkConnection> &
}
}
void CServerHandler::onDisconnected(const std::shared_ptr<NetworkConnection> &)
void CServerHandler::onDisconnected(const std::shared_ptr<INetworkConnection> &)
{
if(state == EClientState::DISCONNECTING)
{

View File

@ -11,7 +11,7 @@
#include "../lib/CStopWatch.h"
#include "../lib/network/NetworkListener.h"
#include "../lib/network/NetworkInterface.h"
#include "../lib/StartInfo.h"
#include "../lib/CondSh.h"
@ -82,11 +82,12 @@ public:
};
/// structure to handle running server and connecting to it
class CServerHandler : public IServerAPI, public LobbyInfo, public INetworkClientListener, boost::noncopyable
class CServerHandler : public IServerAPI, public LobbyInfo, public INetworkClientListener, public INetworkTimerListener, boost::noncopyable
{
friend class ApplyOnLobbyHandlerNetPackVisitor;
std::unique_ptr<NetworkClient> networkClient;
std::unique_ptr<INetworkHandler> networkHandler;
std::unique_ptr<INetworkClient> networkClient;
std::unique_ptr<GlobalLobbyClient> lobbyClient;
std::unique_ptr<CApplier<CBaseForLobbyApply>> applier;
std::shared_ptr<CMapInfo> mapToStart;
@ -98,10 +99,10 @@ class CServerHandler : public IServerAPI, public LobbyInfo, public INetworkClien
void onServerFinished();
void sendLobbyPack(const CPackForLobby & pack) const override;
void onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message) override;
void onPacketReceived(const std::shared_ptr<INetworkConnection> &, const std::vector<uint8_t> & message) override;
void onConnectionFailed(const std::string & errorMessage) override;
void onConnectionEstablished(const std::shared_ptr<NetworkConnection> &) override;
void onDisconnected(const std::shared_ptr<NetworkConnection> &) override;
void onConnectionEstablished(const std::shared_ptr<INetworkConnection> &) override;
void onDisconnected(const std::shared_ptr<INetworkConnection> &) override;
void onTimer() override;
void applyPackOnLobbyScreen(CPackForLobby & pack);

View File

@ -21,21 +21,12 @@
#include "../../lib/CConfigHandler.h"
#include "../../lib/MetaString.h"
#include "../../lib/TextOperations.h"
#include "../../lib/network/NetworkClient.h"
GlobalLobbyClient::~GlobalLobbyClient()
{
networkClient->stop();
networkThread->join();
}
GlobalLobbyClient::~GlobalLobbyClient() = default;
GlobalLobbyClient::GlobalLobbyClient()
: networkClient(std::make_unique<NetworkClient>(*this))
{
networkThread = std::make_unique<boost::thread>([this](){
networkClient->run();
});
}
GlobalLobbyClient::GlobalLobbyClient(const std::unique_ptr<INetworkHandler> & handler)
: networkClient(handler->createClientTCP(*this))
{}
static std::string getCurrentTimeFormatted(int timeOffsetSeconds = 0)
{
@ -46,7 +37,7 @@ static std::string getCurrentTimeFormatted(int timeOffsetSeconds = 0)
return TextOperations::getFormattedTimeLocal(std::chrono::system_clock::to_time_t(timeNowChrono));
}
void GlobalLobbyClient::onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message)
void GlobalLobbyClient::onPacketReceived(const std::shared_ptr<INetworkConnection> &, const std::vector<uint8_t> & message)
{
boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex);
@ -158,7 +149,7 @@ void GlobalLobbyClient::receiveActiveAccounts(const JsonNode & json)
//}
}
void GlobalLobbyClient::onConnectionEstablished(const std::shared_ptr<NetworkConnection> &)
void GlobalLobbyClient::onConnectionEstablished(const std::shared_ptr<INetworkConnection> &)
{
JsonNode toSend;
@ -198,17 +189,12 @@ void GlobalLobbyClient::onConnectionFailed(const std::string & errorMessage)
loginWindowPtr->onConnectionFailed(errorMessage);
}
void GlobalLobbyClient::onDisconnected(const std::shared_ptr<NetworkConnection> &)
void GlobalLobbyClient::onDisconnected(const std::shared_ptr<INetworkConnection> &)
{
GH.windows().popWindows(1);
CInfoWindow::showInfoDialog("Connection to game lobby was lost!", {});
}
void GlobalLobbyClient::onTimer()
{
// no-op
}
void GlobalLobbyClient::sendMessage(const JsonNode & data)
{
std::string payloadString = data.toJson(true);

View File

@ -9,7 +9,7 @@
*/
#pragma once
#include "../../lib/network/NetworkListener.h"
#include "../../lib/network/NetworkInterface.h"
VCMI_LIB_NAMESPACE_BEGIN
class JsonNode;
@ -20,18 +20,16 @@ class GlobalLobbyWindow;
class GlobalLobbyClient : public INetworkClientListener, boost::noncopyable
{
std::unique_ptr<boost::thread> networkThread;
std::unique_ptr<NetworkClient> networkClient;
std::unique_ptr<INetworkClient> networkClient;
std::weak_ptr<GlobalLobbyLoginWindow> loginWindow;
std::weak_ptr<GlobalLobbyWindow> lobbyWindow;
std::shared_ptr<GlobalLobbyWindow> lobbyWindowLock; // helper strong reference to prevent window destruction on closing
void onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message) override;
void onPacketReceived(const std::shared_ptr<INetworkConnection> &, const std::vector<uint8_t> & message) override;
void onConnectionFailed(const std::string & errorMessage) override;
void onConnectionEstablished(const std::shared_ptr<NetworkConnection> &) override;
void onDisconnected(const std::shared_ptr<NetworkConnection> &) override;
void onTimer() override;
void onConnectionEstablished(const std::shared_ptr<INetworkConnection> &) override;
void onDisconnected(const std::shared_ptr<INetworkConnection> &) override;
void sendClientRegister();
void sendClientLogin();
@ -44,7 +42,7 @@ class GlobalLobbyClient : public INetworkClientListener, boost::noncopyable
void receiveActiveAccounts(const JsonNode & json);
public:
explicit GlobalLobbyClient();
explicit GlobalLobbyClient(const std::unique_ptr<INetworkHandler> & handler);
~GlobalLobbyClient();
void sendMessage(const JsonNode & data);

View File

@ -130,8 +130,11 @@ void InterfaceObjectConfigurable::build(const JsonNode &config)
for(const auto & item : items->Vector())
addWidget(item["name"].String(), buildWidget(item));
pos.w = config["width"].Integer();
pos.h = config["height"].Integer();
// load only if set
if (!config["width"].isNull())
pos.w = config["width"].Integer();
if (!config["height"].isNull())
pos.h = config["height"].Integer();
}
void InterfaceObjectConfigurable::addConditional(const std::string & name, bool active)

View File

@ -126,6 +126,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
${MAIN_LIB_DIR}/network/NetworkClient.cpp
${MAIN_LIB_DIR}/network/NetworkConnection.cpp
${MAIN_LIB_DIR}/network/NetworkHandler.cpp
${MAIN_LIB_DIR}/network/NetworkServer.cpp
${MAIN_LIB_DIR}/networkPacks/NetPacksLib.cpp
@ -478,7 +479,8 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
${MAIN_LIB_DIR}/network/NetworkClient.h
${MAIN_LIB_DIR}/network/NetworkConnection.h
${MAIN_LIB_DIR}/network/NetworkDefines.h
${MAIN_LIB_DIR}/network/NetworkListener.h
${MAIN_LIB_DIR}/network/NetworkHandler.h
${MAIN_LIB_DIR}/network/NetworkInterface.h
${MAIN_LIB_DIR}/network/NetworkServer.h
${MAIN_LIB_DIR}/networkPacks/ArtifactLocation.h

View File

@ -13,9 +13,9 @@
VCMI_LIB_NAMESPACE_BEGIN
NetworkClient::NetworkClient(INetworkClientListener & listener)
: io(new NetworkService)
, socket(new NetworkSocket(*io))
NetworkClient::NetworkClient(INetworkClientListener & listener, const std::shared_ptr<NetworkContext> & context)
: io(context)
, socket(std::make_shared<NetworkSocket>(*context))
, listener(listener)
{
}
@ -39,54 +39,29 @@ void NetworkClient::onConnected(const boost::system::error_code & ec)
return;
}
connection = std::make_shared<NetworkConnection>(socket, *this);
connection = std::make_shared<NetworkConnection>(*this, socket);
connection->start();
listener.onConnectionEstablished(connection);
}
void NetworkClient::run()
{
boost::asio::executor_work_guard<decltype(io->get_executor())> work{io->get_executor()};
io->run();
}
void NetworkClient::poll()
{
io->poll();
}
void NetworkClient::stop()
{
io->stop();
}
bool NetworkClient::isConnected() const
{
return connection != nullptr;
}
void NetworkClient::setTimer(std::chrono::milliseconds duration)
{
auto timer = std::make_shared<NetworkTimer>(*io, duration);
timer->async_wait([this, timer](const boost::system::error_code& error){
if (!error)
listener.onTimer();
});
}
void NetworkClient::sendPacket(const std::vector<uint8_t> & message)
{
connection->sendPacket(message);
}
void NetworkClient::onDisconnected(const std::shared_ptr<NetworkConnection> & connection)
void NetworkClient::onDisconnected(const std::shared_ptr<INetworkConnection> & connection)
{
this->connection.reset();
listener.onDisconnected(connection);
}
void NetworkClient::onPacketReceived(const std::shared_ptr<NetworkConnection> & connection, const std::vector<uint8_t> & message)
void NetworkClient::onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message)
{
listener.onPacketReceived(connection, message);
}

View File

@ -10,15 +10,14 @@
#pragma once
#include "NetworkDefines.h"
#include "NetworkListener.h"
VCMI_LIB_NAMESPACE_BEGIN
class NetworkConnection;
class DLL_LINKAGE NetworkClient : boost::noncopyable, public INetworkConnectionListener
class NetworkClient : public INetworkConnectionListener, public INetworkClient
{
std::shared_ptr<NetworkService> io;
std::shared_ptr<NetworkContext> io;
std::shared_ptr<NetworkSocket> socket;
std::shared_ptr<NetworkConnection> connection;
@ -26,22 +25,17 @@ class DLL_LINKAGE NetworkClient : boost::noncopyable, public INetworkConnectionL
void onConnected(const boost::system::error_code & ec);
void onDisconnected(const std::shared_ptr<NetworkConnection> & connection) override;
void onPacketReceived(const std::shared_ptr<NetworkConnection> & connection, const std::vector<uint8_t> & message) override;
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);
virtual ~NetworkClient() = default;
NetworkClient(INetworkClientListener & listener, const std::shared_ptr<NetworkContext> & context);
bool isConnected() const;
bool isConnected() const override;
void setTimer(std::chrono::milliseconds duration);
void sendPacket(const std::vector<uint8_t> & message);
void sendPacket(const std::vector<uint8_t> & message) override;
void start(const std::string & host, uint16_t port);
void run();
void poll();
void stop();
void start(const std::string & host, uint16_t port) override;
};
VCMI_LIB_NAMESPACE_END

View File

@ -12,7 +12,7 @@
VCMI_LIB_NAMESPACE_BEGIN
NetworkConnection::NetworkConnection(const std::shared_ptr<NetworkSocket> & socket, INetworkConnectionListener & listener)
NetworkConnection::NetworkConnection(INetworkConnectionListener & listener, const std::shared_ptr<NetworkSocket> & socket)
: socket(socket)
, listener(listener)
{

View File

@ -10,11 +10,10 @@
#pragma once
#include "NetworkDefines.h"
#include "NetworkListener.h"
VCMI_LIB_NAMESPACE_BEGIN
class DLL_LINKAGE NetworkConnection :public std::enable_shared_from_this<NetworkConnection>, boost::noncopyable
class NetworkConnection : public INetworkConnection, public std::enable_shared_from_this<NetworkConnection>
{
static const int messageHeaderSize = sizeof(uint32_t);
static const int messageMaxSize = 64 * 1024 * 1024; // arbitrary size to prevent potential massive allocation if we receive garbage input
@ -29,10 +28,10 @@ class DLL_LINKAGE NetworkConnection :public std::enable_shared_from_this<Network
uint32_t readPacketSize();
public:
NetworkConnection(const std::shared_ptr<NetworkSocket> & socket, INetworkConnectionListener & listener);
NetworkConnection(INetworkConnectionListener & listener, const std::shared_ptr<NetworkSocket> & socket);
void start();
void sendPacket(const std::vector<uint8_t> & message);
void sendPacket(const std::vector<uint8_t> & message) override;
};
VCMI_LIB_NAMESPACE_END

View File

@ -11,9 +11,11 @@
#include <boost/asio.hpp>
#include "NetworkInterface.h"
VCMI_LIB_NAMESPACE_BEGIN
using NetworkService = boost::asio::io_service;
using NetworkContext = boost::asio::io_service;
using NetworkSocket = boost::asio::ip::tcp::socket;
using NetworkAcceptor = boost::asio::ip::tcp::acceptor;
using NetworkBuffer = boost::asio::streambuf;

View File

@ -0,0 +1,57 @@
/*
* NetworkHandler.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 "NetworkHandler.h"
#include "NetworkClient.h"
#include "NetworkServer.h"
VCMI_LIB_NAMESPACE_BEGIN
std::unique_ptr<INetworkHandler> INetworkHandler::createHandler()
{
return std::make_unique<NetworkHandler>();
}
NetworkHandler::NetworkHandler()
: io(std::make_shared<NetworkContext>())
{}
std::unique_ptr<INetworkServer> NetworkHandler::createServerTCP(INetworkServerListener & listener)
{
return std::make_unique<NetworkServer>(listener, io);
}
std::unique_ptr<INetworkClient> NetworkHandler::createClientTCP(INetworkClientListener & listener)
{
return std::make_unique<NetworkClient>(listener, io);
}
void NetworkHandler::run()
{
boost::asio::executor_work_guard<decltype(io->get_executor())> work{io->get_executor()};
io->run();
}
void NetworkHandler::createTimer(INetworkTimerListener & listener, std::chrono::milliseconds duration)
{
auto timer = std::make_shared<NetworkTimer>(*io, duration);
timer->async_wait([&listener, timer](const boost::system::error_code& error){
if (!error)
listener.onTimer();
});
}
void NetworkHandler::stop()
{
io->stop();
}
VCMI_LIB_NAMESPACE_END

View File

@ -0,0 +1,31 @@
/*
* NetworkHandler.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 NetworkHandler : public INetworkHandler
{
std::shared_ptr<NetworkContext> io;
public:
NetworkHandler();
std::unique_ptr<INetworkServer> createServerTCP(INetworkServerListener & listener) override;
std::unique_ptr<INetworkClient> createClientTCP(INetworkClientListener & listener) override;
void createTimer(INetworkTimerListener & listener, std::chrono::milliseconds duration) override;
void run() override;
void stop() override;
};
VCMI_LIB_NAMESPACE_END

View File

@ -0,0 +1,104 @@
/*
* NetworkHandler.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
VCMI_LIB_NAMESPACE_BEGIN
/// Base class for connections with other services, either incoming or outgoing
class DLL_LINKAGE INetworkConnection : boost::noncopyable
{
public:
virtual ~INetworkConnection() = default;
virtual void sendPacket(const std::vector<uint8_t> & message) = 0;
};
using NetworkConnectionPtr = std::shared_ptr<INetworkConnection>;
using NetworkConnectionWeakPtr = std::weak_ptr<INetworkConnection>;
/// Base class for outgoing connections support
class DLL_LINKAGE INetworkClient : boost::noncopyable
{
public:
virtual ~INetworkClient() = default;
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
class DLL_LINKAGE INetworkServer : boost::noncopyable
{
public:
virtual ~INetworkServer() = default;
virtual void sendPacket(const std::shared_ptr<INetworkConnection> &, const std::vector<uint8_t> & message) = 0;
virtual void closeConnection(const std::shared_ptr<INetworkConnection> &) = 0;
virtual void start(uint16_t port) = 0;
};
/// Base interface that must be implemented by user of networking API to handle any connection callbacks
class DLL_LINKAGE INetworkConnectionListener
{
public:
virtual void onDisconnected(const std::shared_ptr<INetworkConnection> & connection) = 0;
virtual void onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message) = 0;
virtual ~INetworkConnectionListener() = default;
};
/// Interface that must be implemented by user of networking API to handle outgoing connection callbacks
class DLL_LINKAGE INetworkClientListener : public INetworkConnectionListener
{
public:
virtual void onConnectionFailed(const std::string & errorMessage) = 0;
virtual void onConnectionEstablished(const std::shared_ptr<INetworkConnection> &) = 0;
};
/// Interface that must be implemented by user of networking API to handle incoming connection callbacks
class DLL_LINKAGE INetworkServerListener : public INetworkConnectionListener
{
public:
virtual void onNewConnection(const std::shared_ptr<INetworkConnection> &) = 0;
};
/// Interface that must be implemented by user of networking API to handle timers on network thread
class DLL_LINKAGE INetworkTimerListener
{
public:
virtual ~INetworkTimerListener() = default;
virtual void onTimer() = 0;
};
/// Main class for handling of all network activity
class DLL_LINKAGE INetworkHandler : boost::noncopyable
{
public:
virtual ~INetworkHandler() = default;
/// Constructs default implementation
static std::unique_ptr<INetworkHandler> createHandler();
/// Creates an instance of TCP server that allows to receiving connections on a local port
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;
/// Creates a timer that will be called once, after specified interval has passed
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
virtual void run() = 0;
virtual void stop() = 0;
};
VCMI_LIB_NAMESPACE_END

View File

@ -1,56 +0,0 @@
/*
* NetworkListener.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
VCMI_LIB_NAMESPACE_BEGIN
class NetworkConnection;
class NetworkServer;
class NetworkClient;
using NetworkConnectionPtr = std::shared_ptr<NetworkConnection>;
using NetworkConnectionWeakPtr = std::weak_ptr<NetworkConnection>;
class DLL_LINKAGE INetworkConnectionListener
{
friend class NetworkConnection;
protected:
virtual void onDisconnected(const std::shared_ptr<NetworkConnection> & connection) = 0;
virtual void onPacketReceived(const std::shared_ptr<NetworkConnection> & connection, const std::vector<uint8_t> & message) = 0;
public:
virtual ~INetworkConnectionListener() = default;
};
class DLL_LINKAGE INetworkServerListener : public INetworkConnectionListener
{
friend class NetworkServer;
protected:
virtual void onNewConnection(const std::shared_ptr<NetworkConnection> &) = 0;
virtual void onTimer() = 0;
public:
virtual ~INetworkServerListener() = default;
};
class DLL_LINKAGE INetworkClientListener : public INetworkConnectionListener
{
friend class NetworkClient;
protected:
virtual void onConnectionFailed(const std::string & errorMessage) = 0;
virtual void onConnectionEstablished(const std::shared_ptr<NetworkConnection> &) = 0;
virtual void onTimer() = 0;
public:
virtual ~INetworkClientListener() = default;
};
VCMI_LIB_NAMESPACE_END

View File

@ -13,16 +13,15 @@
VCMI_LIB_NAMESPACE_BEGIN
NetworkServer::NetworkServer(INetworkServerListener & listener)
:listener(listener)
NetworkServer::NetworkServer(INetworkServerListener & listener, const std::shared_ptr<NetworkContext> & context)
: listener(listener)
, io(context)
{
}
void NetworkServer::start(uint16_t port)
{
io = std::make_shared<boost::asio::io_service>();
acceptor = std::make_shared<NetworkAcceptor>(*io, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port));
startAsyncAccept();
}
@ -32,16 +31,6 @@ void NetworkServer::startAsyncAccept()
acceptor->async_accept(*upcomingConnection, std::bind(&NetworkServer::connectionAccepted, this, upcomingConnection, _1));
}
void NetworkServer::run()
{
io->run();
}
void NetworkServer::run(std::chrono::milliseconds duration)
{
io->run_for(duration);
}
void NetworkServer::connectionAccepted(std::shared_ptr<NetworkSocket> upcomingConnection, const boost::system::error_code & ec)
{
if(ec)
@ -50,44 +39,34 @@ void NetworkServer::connectionAccepted(std::shared_ptr<NetworkSocket> upcomingCo
}
logNetwork->info("We got a new connection! :)");
auto connection = std::make_shared<NetworkConnection>(upcomingConnection, *this);
auto connection = std::make_shared<NetworkConnection>(*this, upcomingConnection);
connections.insert(connection);
connection->start();
listener.onNewConnection(connection);
startAsyncAccept();
}
void NetworkServer::sendPacket(const std::shared_ptr<NetworkConnection> & connection, const std::vector<uint8_t> & message)
void NetworkServer::sendPacket(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message)
{
connection->sendPacket(message);
}
void NetworkServer::closeConnection(const std::shared_ptr<NetworkConnection> & connection)
void NetworkServer::closeConnection(const std::shared_ptr<INetworkConnection> & connection)
{
assert(connections.count(connection));
connections.erase(connection);
}
void NetworkServer::onDisconnected(const std::shared_ptr<NetworkConnection> & connection)
void NetworkServer::onDisconnected(const std::shared_ptr<INetworkConnection> & connection)
{
assert(connections.count(connection));
connections.erase(connection);
listener.onDisconnected(connection);
}
void NetworkServer::onPacketReceived(const std::shared_ptr<NetworkConnection> & connection, const std::vector<uint8_t> & message)
void NetworkServer::onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message)
{
listener.onPacketReceived(connection, message);
}
void NetworkServer::setTimer(std::chrono::milliseconds duration)
{
auto timer = std::make_shared<NetworkTimer>(*io, duration);
timer->async_wait([this, timer](const boost::system::error_code& error){
if (!error)
listener.onTimer();
});
}
VCMI_LIB_NAMESPACE_END

View File

@ -10,35 +10,29 @@
#pragma once
#include "NetworkDefines.h"
#include "NetworkListener.h"
VCMI_LIB_NAMESPACE_BEGIN
class NetworkConnection;
class DLL_LINKAGE NetworkServer : boost::noncopyable, public INetworkConnectionListener
class NetworkServer : public INetworkConnectionListener, public INetworkServer
{
std::shared_ptr<NetworkService> io;
std::shared_ptr<NetworkContext> io;
std::shared_ptr<NetworkAcceptor> acceptor;
std::set<std::shared_ptr<NetworkConnection>> connections;
std::set<std::shared_ptr<INetworkConnection>> connections;
INetworkServerListener & listener;
void connectionAccepted(std::shared_ptr<NetworkSocket>, const boost::system::error_code & ec);
void startAsyncAccept();
void onDisconnected(const std::shared_ptr<NetworkConnection> & connection) override;
void onPacketReceived(const std::shared_ptr<NetworkConnection> & connection, const std::vector<uint8_t> & message) override;
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:
explicit NetworkServer(INetworkServerListener & listener);
NetworkServer(INetworkServerListener & listener, const std::shared_ptr<NetworkContext> & context);
void sendPacket(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message);
void closeConnection(const std::shared_ptr<NetworkConnection> &);
void setTimer(std::chrono::milliseconds duration);
void sendPacket(const std::shared_ptr<INetworkConnection> &, const std::vector<uint8_t> & message) override;
void closeConnection(const std::shared_ptr<INetworkConnection> &) override;
void start(uint16_t port);
void run(std::chrono::milliseconds duration);
void run();
void start(uint16_t port) override;
};
VCMI_LIB_NAMESPACE_END

View File

@ -14,7 +14,7 @@
#include "BinarySerializer.h"
#include "../networkPacks/NetPacksBase.h"
#include "../network/NetworkConnection.h"
#include "../network/NetworkInterface.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -55,7 +55,7 @@ int ConnectionPackReader::read(void * data, unsigned size)
return size;
}
CConnection::CConnection(std::weak_ptr<NetworkConnection> networkConnection)
CConnection::CConnection(std::weak_ptr<INetworkConnection> networkConnection)
: networkConnection(networkConnection)
, packReader(std::make_unique<ConnectionPackReader>())
, packWriter(std::make_unique<ConnectionPackWriter>())
@ -100,7 +100,7 @@ CPack * CConnection::retrievePack(const std::vector<uint8_t> & data)
return result;
}
bool CConnection::isMyConnection(const std::shared_ptr<NetworkConnection> & otherConnection) const
bool CConnection::isMyConnection(const std::shared_ptr<INetworkConnection> & otherConnection) const
{
return otherConnection != nullptr && networkConnection.lock() == otherConnection;
}

View File

@ -14,7 +14,7 @@ VCMI_LIB_NAMESPACE_BEGIN
class BinaryDeserializer;
class BinarySerializer;
struct CPack;
class NetworkConnection;
class INetworkConnection;
class ConnectionPackReader;
class ConnectionPackWriter;
class CGameState;
@ -24,7 +24,7 @@ class CGameState;
class DLL_LINKAGE CConnection : boost::noncopyable
{
/// Non-owning pointer to underlying connection
std::weak_ptr<NetworkConnection> networkConnection;
std::weak_ptr<INetworkConnection> networkConnection;
std::unique_ptr<ConnectionPackReader> packReader;
std::unique_ptr<ConnectionPackWriter> packWriter;
@ -39,12 +39,12 @@ class DLL_LINKAGE CConnection : boost::noncopyable
void enableSmartVectorMemberSerializatoin();
public:
bool isMyConnection(const std::shared_ptr<NetworkConnection> & otherConnection) const;
bool isMyConnection(const std::shared_ptr<INetworkConnection> & otherConnection) const;
std::string uuid;
int connectionID;
CConnection(std::weak_ptr<NetworkConnection> networkConnection);
CConnection(std::weak_ptr<INetworkConnection> networkConnection);
~CConnection();
void sendPack(const CPack * pack);

View File

@ -13,8 +13,6 @@
#include "LobbyDatabase.h"
#include "../lib/JsonNode.h"
#include "../lib/network/NetworkConnection.h"
#include "../lib/network/NetworkServer.h"
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
@ -199,11 +197,6 @@ void LobbyServer::sendChatMessage(const NetworkConnectionPtr & target, const std
sendMessage(target, reply);
}
void LobbyServer::onTimer()
{
// no-op
}
void LobbyServer::onNewConnection(const NetworkConnectionPtr & connection)
{
// no-op - waiting for incoming data
@ -544,7 +537,8 @@ LobbyServer::~LobbyServer() = default;
LobbyServer::LobbyServer(const boost::filesystem::path & databasePath)
: database(new LobbyDatabase(databasePath))
, networkServer(new NetworkServer(*this))
, networkHandler(INetworkHandler::createHandler())
, networkServer(networkHandler->createServerTCP(*this))
{
}
@ -555,5 +549,5 @@ void LobbyServer::start(uint16_t port)
void LobbyServer::run()
{
networkServer->run();
networkHandler->run();
}

View File

@ -9,7 +9,7 @@
*/
#pragma once
#include "../lib/network/NetworkListener.h"
#include "../lib/network/NetworkInterface.h"
#include "LobbyDefines.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -35,12 +35,12 @@ class LobbyServer : public INetworkServerListener
{
std::string accountID;
std::string roomID;
std::weak_ptr<NetworkConnection> accountConnection;
std::weak_ptr<NetworkConnection> roomConnection;
std::weak_ptr<INetworkConnection> accountConnection;
std::weak_ptr<INetworkConnection> roomConnection;
};
/// list of connected proxies. All messages received from (key) will be redirected to (value) connection
std::map<NetworkConnectionPtr, std::weak_ptr<NetworkConnection>> activeProxies;
std::map<NetworkConnectionPtr, std::weak_ptr<INetworkConnection>> activeProxies;
/// list of half-established proxies from server that are still waiting for client to connect
std::vector<AwaitingProxyState> awaitingProxies;
@ -52,7 +52,8 @@ class LobbyServer : public INetworkServerListener
std::map<NetworkConnectionPtr, GameRoomState> activeGameRooms;
std::unique_ptr<LobbyDatabase> database;
std::unique_ptr<NetworkServer> networkServer;
std::unique_ptr<INetworkHandler> networkHandler;
std::unique_ptr<INetworkServer> networkServer;
std::string sanitizeChatMessage(const std::string & inputString) const;
bool isAccountNameValid(const std::string & accountName);
@ -63,7 +64,6 @@ class LobbyServer : public INetworkServerListener
void onNewConnection(const NetworkConnectionPtr & connection) override;
void onDisconnected(const NetworkConnectionPtr & connection) override;
void onPacketReceived(const NetworkConnectionPtr & connection, const std::vector<uint8_t> & message) override;
void onTimer() override;
void sendMessage(const NetworkConnectionPtr & target, const JsonNode & json);

View File

@ -36,8 +36,6 @@
#include "CGameHandler.h"
#include "processors/PlayerMessageProcessor.h"
#include "../lib/mapping/CMapInfo.h"
#include "../lib/network/NetworkServer.h"
#include "../lib/network/NetworkClient.h"
#include "../lib/GameConstants.h"
#include "../lib/logging/CBasicLogConfigurator.h"
#include "../lib/CConfigHandler.h"
@ -164,14 +162,15 @@ CVCMIServer::CVCMIServer(boost::program_options::variables_map & opts)
port = cmdLineOptions["port"].as<uint16_t>();
logNetwork->info("Port %d will be used", port);
networkServer = std::make_unique<NetworkServer>(*this);
networkHandler = INetworkHandler::createHandler();
networkServer = networkHandler->createServerTCP(*this);
networkServer->start(port);
logNetwork->info("Listening for connections at port %d", port);
}
CVCMIServer::~CVCMIServer() = default;
void CVCMIServer::onNewConnection(const std::shared_ptr<NetworkConnection> & connection)
void CVCMIServer::onNewConnection(const std::shared_ptr<INetworkConnection> & connection)
{
if (activeConnections.empty())
establishOutgoingConnection();
@ -187,7 +186,7 @@ void CVCMIServer::onNewConnection(const std::shared_ptr<NetworkConnection> & con
}
}
void CVCMIServer::onPacketReceived(const std::shared_ptr<NetworkConnection> & connection, const std::vector<uint8_t> & message)
void CVCMIServer::onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message)
{
std::shared_ptr<CConnection> c = findConnection(connection);
auto pack = c->retrievePack(message);
@ -201,7 +200,7 @@ void CVCMIServer::onConnectionFailed(const std::string & errorMessage)
//TODO: handle failure to connect to lobby
}
void CVCMIServer::onConnectionEstablished(const std::shared_ptr<NetworkConnection> &)
void CVCMIServer::onConnectionEstablished(const std::shared_ptr<INetworkConnection> &)
{
//TODO: handle connection to lobby - login?
}
@ -216,7 +215,7 @@ EServerState CVCMIServer::getState() const
return state;
}
std::shared_ptr<CConnection> CVCMIServer::findConnection(const std::shared_ptr<NetworkConnection> & netConnection)
std::shared_ptr<CConnection> CVCMIServer::findConnection(const std::shared_ptr<INetworkConnection> & netConnection)
{
for (auto const & gameConnection : activeConnections)
{
@ -236,7 +235,7 @@ void CVCMIServer::run()
vmHelper.callStaticVoidMethod(CAndroidVMHelper::NATIVE_METHODS_DEFAULT_CLASS, "onServerReady");
}
#endif
networkServer->run();
networkHandler->run();
}
void CVCMIServer::onTimer()
@ -258,7 +257,7 @@ void CVCMIServer::onTimer()
if (msDelta.count())
gh->tick(msDelta.count());
networkServer->setTimer(serverUpdateInterval);
networkHandler->createTimer(*this, serverUpdateInterval);
}
void CVCMIServer::establishOutgoingConnection()
@ -269,7 +268,7 @@ void CVCMIServer::establishOutgoingConnection()
std::string hostname = settings["lobby"]["hostname"].String();
int16_t port = settings["lobby"]["port"].Integer();
outgoingConnection = std::make_unique<NetworkClient>(*this);
outgoingConnection = networkHandler->createClientTCP(*this);
outgoingConnection->start(hostname, port);
}
@ -370,7 +369,7 @@ void CVCMIServer::startGameImmediately()
onTimer();
}
void CVCMIServer::onDisconnected(const std::shared_ptr<NetworkConnection> & connection)
void CVCMIServer::onDisconnected(const std::shared_ptr<INetworkConnection> & connection)
{
logNetwork->error("Network error receiving a pack. Connection has been closed");
@ -998,7 +997,8 @@ static void handleCommandOptions(int argc, const char * argv[], boost::program_o
("help,h", "display help and exit")
("version,v", "display version information and exit")
("run-by-client", "indicate that server launched by client on same machine")
("port", po::value<ui16>(), "port at which server will listen to connections from client");
("port", po::value<ui16>(), "port at which server will listen to connections from client")
("lobby", "start server in lobby mode in which server connects to a global lobby");
if(argc > 1)
{

View File

@ -9,7 +9,7 @@
*/
#pragma once
#include "../lib/network/NetworkListener.h"
#include "../lib/network/NetworkInterface.h"
#include "../lib/StartInfo.h"
#include <boost/program_options/variables_map.hpp>
@ -47,13 +47,15 @@ enum class EServerState : ui8
SHUTDOWN
};
class CVCMIServer : public LobbyInfo, public INetworkServerListener, public INetworkClientListener
class CVCMIServer : public LobbyInfo, public INetworkServerListener, public INetworkClientListener, public INetworkTimerListener
{
std::unique_ptr<INetworkHandler> networkHandler;
/// Network server instance that receives and processes incoming connections on active socket
std::unique_ptr<NetworkServer> networkServer;
std::unique_ptr<INetworkServer> networkServer;
/// Outgoing connection established by this server to game lobby for proxy mode (only in lobby game)
std::unique_ptr<NetworkClient> outgoingConnection;
std::unique_ptr<INetworkClient> outgoingConnection;
std::chrono::steady_clock::time_point gameplayStartTime;
std::chrono::steady_clock::time_point lastTimerUpdateTime;
@ -70,16 +72,16 @@ private:
EServerState state;
// INetworkListener impl
void onDisconnected(const std::shared_ptr<NetworkConnection> & connection) override;
void onPacketReceived(const std::shared_ptr<NetworkConnection> & connection, const std::vector<uint8_t> & message) override;
void onNewConnection(const std::shared_ptr<NetworkConnection> &) override;
void onDisconnected(const std::shared_ptr<INetworkConnection> & connection) override;
void onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message) override;
void onNewConnection(const std::shared_ptr<INetworkConnection> &) override;
void onConnectionFailed(const std::string & errorMessage) override;
void onConnectionEstablished(const std::shared_ptr<NetworkConnection> &) override;
void onConnectionEstablished(const std::shared_ptr<INetworkConnection> &) override;
void onTimer() override;
void establishOutgoingConnection();
std::shared_ptr<CConnection> findConnection(const std::shared_ptr<NetworkConnection> &);
std::shared_ptr<CConnection> findConnection(const std::shared_ptr<INetworkConnection> &);
int currentClientId;
ui8 currentPlayerId;