Browse Source

Add proxy connection mode for lobby rooms

Ivan Savenko 1 year ago
parent
commit
033b2889c4

+ 1 - 1
CI/linux/before_install.sh

@@ -7,4 +7,4 @@ sudo apt-get install libboost-all-dev \
 libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev \
 qtbase5-dev \
 ninja-build zlib1g-dev libavformat-dev libswscale-dev libtbb-dev libluajit-5.1-dev \
-libminizip-dev libfuzzylite-dev qttools5-dev # Optional dependencies
+libminizip-dev libfuzzylite-dev qttools5-dev libsqlite3-dev # Optional dependencies

+ 6 - 1
CMakeLists.txt

@@ -41,6 +41,7 @@ if(NOT CMAKE_BUILD_TYPE)
 	set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo)
 endif()
 
+set(buildLobby OFF)
 set(singleProcess OFF)
 set(staticAI OFF)
 if(ANDROID)
@@ -89,8 +90,12 @@ if(NOT APPLE_IOS AND NOT ANDROID)
 	option(ENABLE_MONOLITHIC_INSTALL "Install everything in single directory on Linux and Mac" OFF)
 endif()
 
+if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
+	set(buildLobby ON)
+endif()
+
 if(NOT APPLE_IOS AND NOT ANDROID)
-	option(ENABLE_LOBBY "Enable compilation of lobby server" ON)
+	option(ENABLE_LOBBY "Enable compilation of lobby server" ${buildLobby})
 endif()
 
 option(ENABLE_CCACHE "Speed up recompilation by caching previous compilations" OFF)

+ 7 - 6
server/CVCMIServer.h

@@ -70,12 +70,6 @@ private:
 	std::shared_ptr<CApplier<CBaseForServerApply>> applier;
 	EServerState state;
 
-	// INetworkListener impl
-	void onDisconnected(const std::shared_ptr<INetworkConnection> & connection) override;
-	void onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message) override;
-	void onNewConnection(const std::shared_ptr<INetworkConnection> &) override;
-	void onTimer() override;
-
 	void establishOutgoingConnection();
 
 	std::shared_ptr<CConnection> findConnection(const std::shared_ptr<INetworkConnection> &);
@@ -84,6 +78,13 @@ private:
 	ui8 currentPlayerId;
 
 public:
+	// INetworkListener impl
+	void onDisconnected(const std::shared_ptr<INetworkConnection> & connection) override;
+	void onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message) override;
+	void onNewConnection(const std::shared_ptr<INetworkConnection> &) override;
+	void onTimer() override;
+
+
 	std::shared_ptr<CGameHandler> gh;
 	boost::program_options::variables_map cmdLineOptions;
 

+ 41 - 10
server/GlobalLobbyProcessor.cpp

@@ -15,11 +15,16 @@
 
 GlobalLobbyProcessor::GlobalLobbyProcessor(CVCMIServer & owner)
 	: owner(owner)
+{
+	logGlobal->info("Connecting to lobby server");
+	establishNewConnection();
+}
+
+void GlobalLobbyProcessor::establishNewConnection()
 {
 	std::string hostname = settings["lobby"]["hostname"].String();
 	int16_t port = settings["lobby"]["port"].Integer();
 	owner.networkHandler->connectToRemote(*this, hostname, port);
-	logGlobal->info("Connecting to lobby server");
 }
 
 void GlobalLobbyProcessor::onDisconnected(const std::shared_ptr<INetworkConnection> & connection)
@@ -56,7 +61,12 @@ void GlobalLobbyProcessor::receiveLoginSuccess(const JsonNode & json)
 
 void GlobalLobbyProcessor::receiveAccountJoinsRoom(const JsonNode & json)
 {
-	// TODO: establish new connection to lobby, login, and transfer connection to our owner
+	std::string accountID = json["accountID"].String();
+
+	assert(proxyConnections.count(accountID) == 0);
+
+	proxyConnections[accountID] = nullptr;
+	establishNewConnection();
 }
 
 void GlobalLobbyProcessor::onConnectionFailed(const std::string & errorMessage)
@@ -66,14 +76,35 @@ void GlobalLobbyProcessor::onConnectionFailed(const std::string & errorMessage)
 
 void GlobalLobbyProcessor::onConnectionEstablished(const std::shared_ptr<INetworkConnection> & connection)
 {
-	controlConnection = connection;
-	logGlobal->info("Connection to lobby server established");
-
-	JsonNode toSend;
-	toSend["type"].String() = "serverLogin";
-	toSend["accountID"] = settings["lobby"]["accountID"];
-	toSend["accountCookie"] = settings["lobby"]["accountCookie"];
-	sendMessage(toSend);
+	if (controlConnection == nullptr)
+	{
+		controlConnection = connection;
+		logGlobal->info("Connection to lobby server established");
+
+		JsonNode toSend;
+		toSend["type"].String() = "serverLogin";
+		toSend["accountID"] = settings["lobby"]["accountID"];
+		toSend["accountCookie"] = settings["lobby"]["accountCookie"];
+		sendMessage(toSend);
+	}
+	else
+	{
+		// Proxy connection for a player
+		std::string accountID;
+		for (auto const & proxies : proxyConnections)
+			if (proxies.second == nullptr)
+				accountID = proxies.first;
+
+		JsonNode toSend;
+		toSend["type"].String() = "serverProxyLogin";
+		toSend["gameRoomID"].String() = "";
+		toSend["accountID"].String() = accountID;
+		toSend["accountCookie"] = settings["lobby"]["accountCookie"];
+		sendMessage(toSend);
+
+		proxyConnections[accountID] = connection;
+		owner.onNewConnection(connection);
+	}
 }
 
 void GlobalLobbyProcessor::sendMessage(const JsonNode & data)

+ 3 - 1
server/GlobalLobbyProcessor.h

@@ -22,7 +22,7 @@ class GlobalLobbyProcessor : public INetworkClientListener
 	CVCMIServer & owner;
 
 	std::shared_ptr<INetworkConnection> controlConnection;
-//	std::set<std::shared_ptr<INetworkConnection>> proxyConnections;
+	std::map<std::string, std::shared_ptr<INetworkConnection>> proxyConnections;
 
 	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 +34,8 @@ class GlobalLobbyProcessor : public INetworkClientListener
 	void receiveLoginFailed(const JsonNode & json);
 	void receiveLoginSuccess(const JsonNode & json);
 	void receiveAccountJoinsRoom(const JsonNode & json);
+
+	void establishNewConnection();
 public:
 	GlobalLobbyProcessor(CVCMIServer & owner);
 };