Explorar o código

Implemented message receiving / broadcasting

Ivan Savenko hai 1 ano
pai
achega
de5227142b

+ 42 - 13
client/serverLobby/LobbyWindow.cpp

@@ -17,6 +17,7 @@
 #include "../windows/InfoWindows.h"
 
 #include "../../lib/MetaString.h"
+#include "../../lib/CConfigHandler.h"
 
 LobbyClient::LobbyClient(LobbyWindow * window)
 	: window(window)
@@ -24,6 +25,23 @@ LobbyClient::LobbyClient(LobbyWindow * window)
 
 }
 
+static std::string getCurrentTimeFormatted(int timeOffsetSeconds = 0)
+{
+	// FIXME: better/unified way to format date
+	auto timeNowChrono = std::chrono::system_clock::now();
+	timeNowChrono += std::chrono::seconds(timeOffsetSeconds);
+
+	std::time_t timeNowC = std::chrono::system_clock::to_time_t(timeNowChrono);
+	std::tm timeNowTm = *std::localtime(&timeNowC);
+
+	MetaString timeFormatted;
+	timeFormatted.appendRawString("%d:%d");
+	timeFormatted.replaceNumber(timeNowTm.tm_hour);
+	timeFormatted.replaceNumber(timeNowTm.tm_min);
+
+	return timeFormatted.toString();
+}
+
 void LobbyClient::onPacketReceived(const std::vector<uint8_t> & message)
 {
 	// FIXME: find better approach
@@ -37,22 +55,27 @@ void LobbyClient::onPacketReceived(const std::vector<uint8_t> & message)
 			std::string senderName = entry["senderName"].String();
 			std::string messageText = entry["messageText"].String();
 			int ageSeconds = entry["ageSeconds"].Integer();
+			std::string timeFormatted = getCurrentTimeFormatted(-ageSeconds);
+			window->onGameChatMessage(senderName, messageText, timeFormatted);
+		}
+	}
 
-			// FIXME: better/unified way to format date
-			auto timeNowChrono = std::chrono::system_clock::now();
-			timeNowChrono -= std::chrono::seconds(ageSeconds);
-
-			std::time_t timeNowC = std::chrono::system_clock::to_time_t(timeNowChrono);
-			std::tm timeNowTm = *std::localtime(&timeNowC);
+	if (json["type"].String() == "chatMessage")
+	{
+		std::string senderName = json["senderName"].String();
+		std::string messageText = json["messageText"].String();
+		std::string timeFormatted = getCurrentTimeFormatted();
+		window->onGameChatMessage(senderName, messageText, timeFormatted);
+	}
+}
 
-			MetaString dateFormatted;
-			dateFormatted.appendRawString("%d:%d");
-			dateFormatted.replaceNumber(timeNowTm.tm_hour);
-			dateFormatted.replaceNumber(timeNowTm.tm_min);
+void LobbyClient::onConnectionEstablished()
+{
+	JsonNode toSend;
+	toSend["type"].String() = "authentication";
+	toSend["accountName"].String() = settings["general"]["playerName"].String();
 
-			window->onGameChatMessage(senderName, messageText, dateFormatted.toString());
-		}
-	}
+	sendMessage(toSend);
 }
 
 void LobbyClient::onConnectionFailed(const std::string & errorMessage)
@@ -90,6 +113,11 @@ LobbyWidget::LobbyWidget(LobbyWindow * window)
 	build(config);
 }
 
+std::shared_ptr<CLabel> LobbyWidget::getAccountNameLabel()
+{
+	return widget<CLabel>("accountNameLabel");
+}
+
 std::shared_ptr<CTextInput> LobbyWidget::getMessageInput()
 {
 	return widget<CTextInput>("messageInput");
@@ -110,6 +138,7 @@ LobbyWindow::LobbyWindow():
 	connection = std::make_shared<LobbyClient>(this);
 
 	connection->start("127.0.0.1", 30303);
+	widget->getAccountNameLabel()->setText(settings["general"]["playerName"].String());
 
 	addUsedEvents(TIME);
 }

+ 2 - 0
client/serverLobby/LobbyWindow.h

@@ -22,6 +22,7 @@ class LobbyWidget : public InterfaceObjectConfigurable
 public:
 	LobbyWidget(LobbyWindow * window);
 
+	std::shared_ptr<CLabel> getAccountNameLabel();
 	std::shared_ptr<CTextInput> getMessageInput();
 	std::shared_ptr<CTextBox> getGameChat();
 };
@@ -32,6 +33,7 @@ class LobbyClient : public NetworkClient
 
 	void onPacketReceived(const std::vector<uint8_t> & message) override;
 	void onConnectionFailed(const std::string & errorMessage) override;
+	void onConnectionEstablished() override;
 	void onDisconnected() override;
 
 public:

+ 3 - 4
config/widgets/lobbyWindow.json

@@ -41,9 +41,9 @@
 			"rect": {"x": 5, "y": 5, "w": 250, "h": 40}
 		},
 		{
+			"name" : "accountNameLabel",
 			"type": "labelTitleMain",
-			"position": {"x": 15, "y": 10},
-			"text" : "Player Name"
+			"position": {"x": 15, "y": 10}
 		},
 		
 		{
@@ -91,8 +91,7 @@
 			"font": "small",
 			"alignment": "left",
 			"color": "white",
-			"text": "[00:00]{Player 1}: Hello\n[00:01]{Player 2}: HI!",
-			"rect": {"x": 430, "y": 70, "w": 430, "h": 495}
+			"rect": {"x": 440, "y": 70, "w": 430, "h": 495}
 		},
 		
 		{

+ 2 - 0
lib/network/NetworkClient.cpp

@@ -38,6 +38,8 @@ void NetworkClient::onConnected(const boost::system::error_code & ec)
 
 	connection = std::make_shared<NetworkConnection>(socket, *this);
 	connection->start();
+
+	onConnectionEstablished();
 }
 
 void NetworkClient::run()

+ 1 - 0
lib/network/NetworkClient.h

@@ -30,6 +30,7 @@ class DLL_LINKAGE NetworkClient : boost::noncopyable, public INetworkConnectionL
 protected:
 	virtual void onPacketReceived(const std::vector<uint8_t> & message) = 0;
 	virtual void onConnectionFailed(const std::string & errorMessage) = 0;
+	virtual void onConnectionEstablished() = 0;
 	virtual void onDisconnected() = 0;
 
 	void sendPacket(const std::vector<uint8_t> & message);

+ 1 - 1
lib/network/NetworkConnection.h

@@ -16,7 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 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;
+	static const int messageMaxSize = 65536; // arbitrary size to prevent potential massive allocation if we receive garbage input
 
 	std::shared_ptr<NetworkSocket> socket;
 

+ 1 - 0
lib/network/NetworkServer.cpp

@@ -56,6 +56,7 @@ void NetworkServer::onDisconnected(const std::shared_ptr<NetworkConnection> & co
 {
 	assert(connections.count(connection));
 	connections.erase(connection);
+	onConnectionLost(connection);
 }
 
 VCMI_LIB_NAMESPACE_END

+ 1 - 0
lib/network/NetworkServer.h

@@ -27,6 +27,7 @@ class DLL_LINKAGE NetworkServer : boost::noncopyable, public INetworkConnectionL
 	void onDisconnected(const std::shared_ptr<NetworkConnection> & connection) override;
 protected:
 	virtual void onNewConnection(const std::shared_ptr<NetworkConnection> &) = 0;
+	virtual void onConnectionLost(const std::shared_ptr<NetworkConnection> &) = 0;
 
 	void sendPacket(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message);
 

+ 45 - 19
lobby/LobbyServer.cpp

@@ -109,27 +109,14 @@ void LobbyServer::sendMessage(const std::shared_ptr<NetworkConnection> & target,
 
 void LobbyServer::onNewConnection(const std::shared_ptr<NetworkConnection> & connection)
 {
-	// FIXME: move to authorization message reply
-	auto history = database->getRecentMessageHistory();
-
-	JsonNode json;
-	json["type"].String() = "chatHistory";
-
-	for (auto const & message : boost::adaptors::reverse(history))
-	{
-		JsonNode jsonEntry;
-
-		jsonEntry["messageText"].String() = message.messageText;
-		jsonEntry["senderName"].String() = message.sender;
-		jsonEntry["ageSeconds"].Integer() = message.messageAgeSeconds;
-
-		json["messages"].Vector().push_back(jsonEntry);
-	}
+}
 
-	sendMessage(connection, json);
+void LobbyServer::onConnectionLost(const std::shared_ptr<NetworkConnection> & connection)
+{
+	activeAccounts.erase(connection);
 }
 
-void LobbyServer::onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message)
+void LobbyServer::onPacketReceived(const std::shared_ptr<NetworkConnection> & connection, const std::vector<uint8_t> & message)
 {
 	// FIXME: find better approach
 	const char * payloadBegin = reinterpret_cast<const char*>(message.data());
@@ -137,7 +124,46 @@ void LobbyServer::onPacketReceived(const std::shared_ptr<NetworkConnection> &, c
 
 	if (json["type"].String() == "sendChatMessage")
 	{
-		database->insertChatMessage("Unknown", json["messageText"].String());
+		if (activeAccounts.count(connection) == 0)
+			return; // unauthenticated
+
+		std::string senderName = activeAccounts[connection].accountName;
+		std::string messageText = json["messageText"].String();
+
+		database->insertChatMessage(senderName, messageText);
+
+		JsonNode reply;
+		reply["type"].String() = "chatMessage";
+		reply["messageText"].String() = messageText;
+		reply["senderName"].String() = senderName;
+
+		for (auto const & connection : activeAccounts)
+			sendMessage(connection.first, reply);
+	}
+
+	if (json["type"].String() == "authentication")
+	{
+		std::string accountName = json["accountName"].String();
+
+		activeAccounts[connection].accountName = accountName;
+
+		auto history = database->getRecentMessageHistory();
+
+		JsonNode json;
+		json["type"].String() = "chatHistory";
+
+		for (auto const & message : boost::adaptors::reverse(history))
+		{
+			JsonNode jsonEntry;
+
+			jsonEntry["messageText"].String() = message.messageText;
+			jsonEntry["senderName"].String() = message.sender;
+			jsonEntry["ageSeconds"].Integer() = message.messageAgeSeconds;
+
+			json["messages"].Vector().push_back(jsonEntry);
+		}
+
+		sendMessage(connection, json);
 	}
 }
 

+ 8 - 0
lobby/LobbyServer.h

@@ -43,9 +43,17 @@ public:
 
 class LobbyServer : public NetworkServer
 {
+	struct AccountState
+	{
+		std::string accountName;
+	};
+
+	std::map<std::shared_ptr<NetworkConnection>, AccountState> activeAccounts;
+
 	std::unique_ptr<LobbyDatabase> database;
 
 	void onNewConnection(const std::shared_ptr<NetworkConnection> &) override;
+	void onConnectionLost(const std::shared_ptr<NetworkConnection> &) override;
 	void onPacketReceived(const std::shared_ptr<NetworkConnection> &, const std::vector<uint8_t> & message) override;
 
 	void sendMessage(const std::shared_ptr<NetworkConnection> & target, const JsonNode & json);