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