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

Implemented connection handling

This commit is contained in:
Ivan Savenko 2023-11-12 13:27:22 +02:00
parent c2c43602ea
commit dff9cf39c0
11 changed files with 106 additions and 40 deletions

View File

@ -14,11 +14,25 @@
#include "../gui/CGuiHandler.h"
#include "../gui/WindowHandler.h"
#include "../windows/InfoWindows.h"
void LobbyClient::onPacketReceived(const std::vector<uint8_t> & message)
{
}
void LobbyClient::onConnectionFailed(const std::string & errorMessage)
{
GH.windows().popWindows(1);
CInfoWindow::showInfoDialog("Failed to connect to game lobby!\n" + errorMessage, {});
}
void LobbyClient::onDisconnected()
{
GH.windows().popWindows(1);
CInfoWindow::showInfoDialog("Connection to game lobby was lost!", {});
}
LobbyWidget::LobbyWidget()
{
addCallback("closeWindow", [](int) { GH.windows().popWindows(1); });
@ -37,4 +51,11 @@ LobbyWindow::LobbyWindow():
connection = std::make_shared<LobbyClient>();
connection->start("127.0.0.1", 30303);
addUsedEvents(TIME);
}
void LobbyWindow::tick(uint32_t msPassed)
{
connection->poll();
}

View File

@ -23,6 +23,8 @@ public:
class LobbyClient : public NetworkClient
{
void onPacketReceived(const std::vector<uint8_t> & message) override;
void onConnectionFailed(const std::string & errorMessage) override;
void onDisconnected() override;
public:
LobbyClient() = default;
};
@ -32,6 +34,8 @@ class LobbyWindow : public CWindowObject
std::shared_ptr<LobbyWidget> widget;
std::shared_ptr<LobbyClient> connection;
void tick(uint32_t msPassed);
public:
LobbyWindow();
};

View File

@ -30,7 +30,13 @@ void NetworkClient::start(const std::string & host, uint16_t port)
void NetworkClient::onConnected(const boost::system::error_code & ec)
{
connection = std::make_shared<NetworkConnection>(socket);
if (ec)
{
onConnectionFailed(ec.message());
return;
}
connection = std::make_shared<NetworkConnection>(socket, *this);
connection->start();
}
@ -39,9 +45,25 @@ void NetworkClient::run()
io->run();
}
void NetworkClient::poll()
{
io->poll();
}
void NetworkClient::sendPacket(const std::vector<uint8_t> & message)
{
connection->sendPacket(message);
}
void NetworkClient::onDisconnected(const std::shared_ptr<NetworkConnection> & connection)
{
onDisconnected();
}
void NetworkClient::onPacketReceived(const std::shared_ptr<NetworkConnection> & connection, const std::vector<uint8_t> & message)
{
onPacketReceived(message);
}
VCMI_LIB_NAMESPACE_END

View File

@ -15,7 +15,7 @@ VCMI_LIB_NAMESPACE_BEGIN
class NetworkConnection;
class DLL_LINKAGE NetworkClient : boost::noncopyable
class DLL_LINKAGE NetworkClient : boost::noncopyable, public INetworkConnectionListener
{
std::shared_ptr<NetworkService> io;
std::shared_ptr<NetworkSocket> socket;
@ -23,8 +23,15 @@ class DLL_LINKAGE NetworkClient : boost::noncopyable
std::shared_ptr<NetworkTimer> timer;
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;
protected:
virtual void onPacketReceived(const std::vector<uint8_t> & message) = 0;
virtual void onConnectionFailed(const std::string & errorMessage) = 0;
virtual void onDisconnected() = 0;
public:
NetworkClient();
virtual ~NetworkClient() = default;
@ -32,6 +39,7 @@ public:
void start(const std::string & host, uint16_t port);
void sendPacket(const std::vector<uint8_t> & message);
void run();
void poll();
};
VCMI_LIB_NAMESPACE_END

View File

@ -12,8 +12,9 @@
VCMI_LIB_NAMESPACE_BEGIN
NetworkConnection::NetworkConnection(const std::shared_ptr<NetworkSocket> & socket)
NetworkConnection::NetworkConnection(const std::shared_ptr<NetworkSocket> & socket, INetworkConnectionListener & listener)
: socket(socket)
, listener(listener)
{
}
@ -28,7 +29,13 @@ void NetworkConnection::start()
void NetworkConnection::onHeaderReceived(const boost::system::error_code & ec)
{
uint32_t messageSize = readPacketSize(ec);
if (ec)
{
listener.onDisconnected(shared_from_this());
return;
}
uint32_t messageSize = readPacketSize();
boost::asio::async_read(*socket,
readBuffer,
@ -36,23 +43,15 @@ void NetworkConnection::onHeaderReceived(const boost::system::error_code & ec)
std::bind(&NetworkConnection::onPacketReceived,this, _1, messageSize));
}
uint32_t NetworkConnection::readPacketSize(const boost::system::error_code & ec)
uint32_t NetworkConnection::readPacketSize()
{
if (ec)
{
throw std::runtime_error("Connection aborted!");
}
if (readBuffer.size() < messageHeaderSize)
{
throw std::runtime_error("Failed to read header!");
}
std::istream istream(&readBuffer);
uint32_t messageSize;
istream.read(reinterpret_cast<char *>(&messageSize), messageHeaderSize);
if (messageSize > messageMaxSize)
{
throw std::runtime_error("Invalid packet size!");
@ -65,7 +64,8 @@ void NetworkConnection::onPacketReceived(const boost::system::error_code & ec, u
{
if (ec)
{
throw std::runtime_error("Connection aborted!");
listener.onDisconnected(shared_from_this());
return;
}
if (readBuffer.size() < expectedPacketSize)
@ -79,6 +79,8 @@ void NetworkConnection::onPacketReceived(const boost::system::error_code & ec, u
std::istream istream(&readBuffer);
istream.read(reinterpret_cast<char *>(message.data()), messageHeaderSize);
listener.onPacketReceived(shared_from_this(), message);
start();
}

View File

@ -13,7 +13,7 @@
VCMI_LIB_NAMESPACE_BEGIN
class DLL_LINKAGE NetworkConnection : boost::noncopyable
class DLL_LINKAGE NetworkConnection :public std::enable_shared_from_this<NetworkConnection>, boost::noncopyable
{
static const int messageHeaderSize = sizeof(uint32_t);
static const int messageMaxSize = 1024;
@ -21,13 +21,14 @@ class DLL_LINKAGE NetworkConnection : boost::noncopyable
std::shared_ptr<NetworkSocket> socket;
NetworkBuffer readBuffer;
INetworkConnectionListener & listener;
void onHeaderReceived(const boost::system::error_code & ec);
void onPacketReceived(const boost::system::error_code & ec, uint32_t expectedPacketSize);
uint32_t readPacketSize(const boost::system::error_code & ec);
uint32_t readPacketSize();
public:
NetworkConnection(const std::shared_ptr<NetworkSocket> & socket);
NetworkConnection(const std::shared_ptr<NetworkSocket> & socket, INetworkConnectionListener & listener);
void start();
void sendPacket(const std::vector<uint8_t> & message);

View File

@ -19,4 +19,15 @@ using NetworkAcceptor = boost::asio::basic_socket_acceptor<boost::asio::ip::tcp>
using NetworkBuffer = boost::asio::streambuf;
using NetworkTimer = boost::asio::steady_timer;
class 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;
};
VCMI_LIB_NAMESPACE_END

View File

@ -36,22 +36,13 @@ void NetworkServer::connectionAccepted(std::shared_ptr<NetworkSocket> upcomingCo
{
if(ec)
{
logNetwork->info("Something wrong during accepting: %s", ec.message());
return;
}
try
{
logNetwork->info("We got a new connection! :)");
auto connection = std::make_shared<NetworkConnection>(upcomingConnection);
connections.insert(connection);
connection->start();
}
catch(std::exception & e)
{
logNetwork->error("Failure processing new connection! %s", e.what());
throw std::runtime_error("Something wrong during accepting: " + ec.message());
}
logNetwork->info("We got a new connection! :)");
auto connection = std::make_shared<NetworkConnection>(upcomingConnection, *this);
connections.insert(connection);
connection->start();
startAsyncAccept();
}
@ -60,4 +51,10 @@ void NetworkServer::sendPacket(const std::shared_ptr<NetworkConnection> & connec
connection->sendPacket(message);
}
void NetworkServer::onDisconnected(const std::shared_ptr<NetworkConnection> & connection)
{
assert(connections.count(connection));
connections.erase(connection);
}
VCMI_LIB_NAMESPACE_END

View File

@ -15,7 +15,7 @@ VCMI_LIB_NAMESPACE_BEGIN
class NetworkConnection;
class DLL_LINKAGE NetworkServer : boost::noncopyable
class DLL_LINKAGE NetworkServer : boost::noncopyable, public INetworkConnectionListener
{
std::shared_ptr<NetworkService> io;
std::shared_ptr<NetworkAcceptor> acceptor;
@ -23,9 +23,10 @@ class DLL_LINKAGE NetworkServer : boost::noncopyable
void connectionAccepted(std::shared_ptr<NetworkSocket>, const boost::system::error_code & ec);
void startAsyncAccept();
void onDisconnected(const std::shared_ptr<NetworkConnection> & connection) override;
protected:
virtual void onNewConnection(std::shared_ptr<NetworkConnection>) = 0;
virtual void onPacketReceived(std::shared_ptr<NetworkConnection>, const std::vector<uint8_t> & message) = 0;
virtual void onNewConnection(const std::shared_ptr<NetworkConnection> &) = 0;
void sendPacket(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message);

View File

@ -15,17 +15,17 @@
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
static const std::string DATABASE_PATH = "~/vcmi.db";
static const std::string DATABASE_PATH = "/home/ivan/vcmi.db";
static const int LISTENING_PORT = 30303;
//static const std::string SERVER_NAME = GameConstants::VCMI_VERSION + " (server)";
//static const std::string SERVER_UUID = boost::uuids::to_string(boost::uuids::random_generator()());
void LobbyServer::onNewConnection(std::shared_ptr<NetworkConnection>)
void LobbyServer::onNewConnection(const std::shared_ptr<NetworkConnection> &)
{
}
void LobbyServer::onPacketReceived(std::shared_ptr<NetworkConnection>, const std::vector<uint8_t> & message)
void LobbyServer::onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message)
{
}
@ -33,7 +33,6 @@ void LobbyServer::onPacketReceived(std::shared_ptr<NetworkConnection>, const std
LobbyServer::LobbyServer()
{
database = SQLiteInstance::open(DATABASE_PATH, true);
}
int main(int argc, const char * argv[])

View File

@ -17,8 +17,8 @@ class LobbyServer : public NetworkServer
{
std::unique_ptr<SQLiteInstance> database;
void onNewConnection(std::shared_ptr<NetworkConnection>) override;
void onPacketReceived(std::shared_ptr<NetworkConnection>, const std::vector<uint8_t> & message) override;
void onNewConnection(const std::shared_ptr<NetworkConnection> &) override;
void onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message) override;
public:
LobbyServer();
};