瀏覽代碼

Simplified networking API

Ivan Savenko 1 年之前
父節點
當前提交
709905b1a0

+ 9 - 5
client/CServerHandler.cpp

@@ -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!");

+ 3 - 2
client/CServerHandler.h

@@ -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;

+ 12 - 9
client/globalLobby/GlobalLobbyClient.cpp

@@ -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()

+ 2 - 2
client/globalLobby/GlobalLobbyClient.h

@@ -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);

+ 0 - 2
cmake_modules/VCMI_lib.cmake

@@ -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

+ 0 - 70
lib/network/NetworkClient.cpp

@@ -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

+ 0 - 41
lib/network/NetworkClient.h

@@ -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

+ 17 - 3
lib/network/NetworkHandler.cpp

@@ -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()

+ 1 - 1
lib/network/NetworkHandler.h

@@ -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;

+ 5 - 2
lib/network/NetworkInterface.h

@@ -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

+ 12 - 4
server/GlobalLobbyProcessor.cpp

@@ -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);
 }

+ 1 - 1
server/GlobalLobbyProcessor.h

@@ -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);
 };