mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Implemented connection handling
This commit is contained in:
		| @@ -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(); | ||||
| } | ||||
|   | ||||
| @@ -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(); | ||||
| }; | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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(); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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[]) | ||||
|   | ||||
| @@ -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(); | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user