diff --git a/client/serverLobby/LobbyWindow.cpp b/client/serverLobby/LobbyWindow.cpp index 635542213..ce7a41e67 100644 --- a/client/serverLobby/LobbyWindow.cpp +++ b/client/serverLobby/LobbyWindow.cpp @@ -14,11 +14,25 @@ #include "../gui/CGuiHandler.h" #include "../gui/WindowHandler.h" +#include "../windows/InfoWindows.h" + void LobbyClient::onPacketReceived(const std::vector & 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(); connection->start("127.0.0.1", 30303); + + addUsedEvents(TIME); +} + +void LobbyWindow::tick(uint32_t msPassed) +{ + connection->poll(); } diff --git a/client/serverLobby/LobbyWindow.h b/client/serverLobby/LobbyWindow.h index 592004b5f..d13c1d1a6 100644 --- a/client/serverLobby/LobbyWindow.h +++ b/client/serverLobby/LobbyWindow.h @@ -23,6 +23,8 @@ public: class LobbyClient : public NetworkClient { void onPacketReceived(const std::vector & 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 widget; std::shared_ptr connection; + void tick(uint32_t msPassed); + public: LobbyWindow(); }; diff --git a/lib/network/NetworkClient.cpp b/lib/network/NetworkClient.cpp index 717939b8e..d46b0ac2e 100644 --- a/lib/network/NetworkClient.cpp +++ b/lib/network/NetworkClient.cpp @@ -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(socket); + if (ec) + { + onConnectionFailed(ec.message()); + return; + } + + connection = std::make_shared(socket, *this); connection->start(); } @@ -39,9 +45,25 @@ void NetworkClient::run() io->run(); } +void NetworkClient::poll() +{ + io->poll(); +} + void NetworkClient::sendPacket(const std::vector & message) { connection->sendPacket(message); } +void NetworkClient::onDisconnected(const std::shared_ptr & connection) +{ + onDisconnected(); +} + +void NetworkClient::onPacketReceived(const std::shared_ptr & connection, const std::vector & message) +{ + onPacketReceived(message); +} + + VCMI_LIB_NAMESPACE_END diff --git a/lib/network/NetworkClient.h b/lib/network/NetworkClient.h index a28809a9a..5cc87a1ec 100644 --- a/lib/network/NetworkClient.h +++ b/lib/network/NetworkClient.h @@ -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 io; std::shared_ptr socket; @@ -23,8 +23,15 @@ class DLL_LINKAGE NetworkClient : boost::noncopyable std::shared_ptr timer; 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; + protected: virtual void onPacketReceived(const std::vector & 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 & message); void run(); + void poll(); }; VCMI_LIB_NAMESPACE_END diff --git a/lib/network/NetworkConnection.cpp b/lib/network/NetworkConnection.cpp index eb0565cad..4c0a26471 100644 --- a/lib/network/NetworkConnection.cpp +++ b/lib/network/NetworkConnection.cpp @@ -12,8 +12,9 @@ VCMI_LIB_NAMESPACE_BEGIN -NetworkConnection::NetworkConnection(const std::shared_ptr & socket) +NetworkConnection::NetworkConnection(const std::shared_ptr & 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(&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(message.data()), messageHeaderSize); + listener.onPacketReceived(shared_from_this(), message); + start(); } diff --git a/lib/network/NetworkConnection.h b/lib/network/NetworkConnection.h index d9894bed1..97b1a7f9a 100644 --- a/lib/network/NetworkConnection.h +++ b/lib/network/NetworkConnection.h @@ -13,7 +13,7 @@ VCMI_LIB_NAMESPACE_BEGIN -class DLL_LINKAGE NetworkConnection : boost::noncopyable +class DLL_LINKAGE NetworkConnection :public std::enable_shared_from_this, 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 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 & socket); + NetworkConnection(const std::shared_ptr & socket, INetworkConnectionListener & listener); void start(); void sendPacket(const std::vector & message); diff --git a/lib/network/NetworkDefines.h b/lib/network/NetworkDefines.h index bbf5dc152..8b05370bb 100644 --- a/lib/network/NetworkDefines.h +++ b/lib/network/NetworkDefines.h @@ -19,4 +19,15 @@ using NetworkAcceptor = boost::asio::basic_socket_acceptor 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 & connection) = 0; + virtual void onPacketReceived(const std::shared_ptr & connection, const std::vector & message) = 0; +}; + VCMI_LIB_NAMESPACE_END diff --git a/lib/network/NetworkServer.cpp b/lib/network/NetworkServer.cpp index 8aa6b70e6..7e201c83f 100644 --- a/lib/network/NetworkServer.cpp +++ b/lib/network/NetworkServer.cpp @@ -36,22 +36,13 @@ void NetworkServer::connectionAccepted(std::shared_ptr 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(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(upcomingConnection, *this); + connections.insert(connection); + connection->start(); startAsyncAccept(); } @@ -60,4 +51,10 @@ void NetworkServer::sendPacket(const std::shared_ptr & connec connection->sendPacket(message); } +void NetworkServer::onDisconnected(const std::shared_ptr & connection) +{ + assert(connections.count(connection)); + connections.erase(connection); +} + VCMI_LIB_NAMESPACE_END diff --git a/lib/network/NetworkServer.h b/lib/network/NetworkServer.h index 5853cb7ac..54cb7c8cd 100644 --- a/lib/network/NetworkServer.h +++ b/lib/network/NetworkServer.h @@ -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 io; std::shared_ptr acceptor; @@ -23,9 +23,10 @@ class DLL_LINKAGE NetworkServer : boost::noncopyable void connectionAccepted(std::shared_ptr, const boost::system::error_code & ec); void startAsyncAccept(); + + void onDisconnected(const std::shared_ptr & connection) override; protected: - virtual void onNewConnection(std::shared_ptr) = 0; - virtual void onPacketReceived(std::shared_ptr, const std::vector & message) = 0; + virtual void onNewConnection(const std::shared_ptr &) = 0; void sendPacket(const std::shared_ptr &, const std::vector & message); diff --git a/lobby/LobbyServer.cpp b/lobby/LobbyServer.cpp index 81648d9ce..cdbc20a58 100644 --- a/lobby/LobbyServer.cpp +++ b/lobby/LobbyServer.cpp @@ -15,17 +15,17 @@ #include #include -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) +void LobbyServer::onNewConnection(const std::shared_ptr &) { } -void LobbyServer::onPacketReceived(std::shared_ptr, const std::vector & message) +void LobbyServer::onPacketReceived(const std::shared_ptr &, const std::vector & message) { } @@ -33,7 +33,6 @@ void LobbyServer::onPacketReceived(std::shared_ptr, const std LobbyServer::LobbyServer() { database = SQLiteInstance::open(DATABASE_PATH, true); - } int main(int argc, const char * argv[]) diff --git a/lobby/LobbyServer.h b/lobby/LobbyServer.h index c3a434a74..329d831b5 100644 --- a/lobby/LobbyServer.h +++ b/lobby/LobbyServer.h @@ -17,8 +17,8 @@ class LobbyServer : public NetworkServer { std::unique_ptr database; - void onNewConnection(std::shared_ptr) override; - void onPacketReceived(std::shared_ptr, const std::vector & message) override; + void onNewConnection(const std::shared_ptr &) override; + void onPacketReceived(const std::shared_ptr &, const std::vector & message) override; public: LobbyServer(); };