From 70e889ebdb224db6811e930c838db07d6719e939 Mon Sep 17 00:00:00 2001
From: SChernykh <15806605+SChernykh@users.noreply.github.com>
Date: Wed, 29 May 2024 10:47:03 +0200
Subject: [PATCH] Fixed software version display

---
 src/p2p_server.cpp | 43 +++++++++++++++++++++++++++++++------------
 src/p2p_server.h   | 11 +++++++++--
 2 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/src/p2p_server.cpp b/src/p2p_server.cpp
index 02484d8..5daa52f 100644
--- a/src/p2p_server.cpp
+++ b/src/p2p_server.cpp
@@ -1047,7 +1047,7 @@ void P2PServer::show_peers() const
 			char buf[32] = {};
 			if (client->m_SoftwareVersion) {
 				log::Stream s(buf);
-				s << client->software_name() << " v" << (client->m_SoftwareVersion >> 16) << '.' << (client->m_SoftwareVersion & 0xFFFF);
+				s << P2PClient::SoftwareDisplayName(client->m_SoftwareID, client->m_SoftwareVersion);
 			}
 			LOGINFO(0, (client->m_isIncoming ? "I\t" : "O\t")
 				<< log::pad_right(log::Duration(cur_time - client->m_connectedTime), 16) << '\t'
@@ -1392,7 +1392,7 @@ void P2PServer::api_update_local_stats()
 					char buf[32] = {};
 					log::Stream s1(buf);
 					if (client->m_SoftwareVersion) {
-						s1 << client->software_name() << " v" << (client->m_SoftwareVersion >> 16) << '.' << (client->m_SoftwareVersion & 0xFFFF);
+						s1 << P2PClient::SoftwareDisplayName(client->m_SoftwareID, client->m_SoftwareVersion);
 					}
 
 					if (!first) {
@@ -2413,7 +2413,7 @@ void P2PServer::P2PClient::on_peer_list_response(const uint8_t* buf)
 
 					LOGINFO(5, "peer " << log::Gray() << static_cast<char*>(m_addrString) << log::NoColor()
 						<< " supports protocol version " << (m_protocolVersion >> 16) << '.' << (m_protocolVersion & 0xFFFF)
-						<< ", runs " << software_name() << " v" << (m_SoftwareVersion >> 16) << '.' << (m_SoftwareVersion & 0xFFFF)
+						<< ", runs " << P2PClient::SoftwareDisplayName(m_SoftwareID, m_SoftwareVersion)
 					);
 
 					if (m_SoftwareID == SoftwareID::Unknown) {
@@ -2682,16 +2682,35 @@ void P2PServer::P2PClient::post_handle_incoming_block(p2pool* pool, const PoolBl
 	}
 }
 
-const char* P2PServer::P2PClient::software_name() const
+template<> struct log::Stream::Entry<P2PServer::P2PClient::SoftwareDisplayName>
 {
-	switch (m_SoftwareID) {
-	case SoftwareID::P2Pool:
-		return "P2Pool";
-	case SoftwareID::GoObserver:
-		return "GoObserver";
-	default:
-		return "Unknown";
+	static NOINLINE void put(P2PServer::P2PClient::SoftwareDisplayName value, Stream* wrapper)
+	{
+		switch (value.m_id) {
+		case SoftwareID::P2Pool:
+			*wrapper << "P2Pool v";
+			if (value.m_version <= 0x3000A) {
+				// Encoding for versions <= 3.10
+				*wrapper << (value.m_version >> 16) << '.' << (value.m_version & 0xFFFF);
+			}
+			else {
+				// Encoding for versions > 3.10
+				*wrapper << (value.m_version >> 16) << '.' << ((value.m_version >> 8) & 0xFF);
+				if (value.m_version & 0xFF) {
+					*wrapper << '.' << (value.m_version & 0xFF);
+				}
+			}
+			break;
+
+		case SoftwareID::GoObserver:
+			*wrapper << "GoObserver v" << (value.m_version >> 16) << '.' << (value.m_version & 0xFFFF);
+			break;
+
+		default:
+			*wrapper << "Unknown v" << (value.m_version >> 16) << '.' << (value.m_version & 0xFFFF);
+			break;
+		}
 	}
-}
+};
 
 } // namespace p2pool
diff --git a/src/p2p_server.h b/src/p2p_server.h
index 6f29aef..b96867d 100644
--- a/src/p2p_server.h
+++ b/src/p2p_server.h
@@ -120,8 +120,6 @@ public:
 
 		[[nodiscard]] bool is_good() const { return m_handshakeComplete && !m_handshakeInvalid && (m_listenPort >= 0); }
 
-		[[nodiscard]] const char* software_name() const;
-
 		alignas(8) char m_p2pReadBuf[P2P_BUF_SIZE];
 
 		uint64_t m_peerId;
@@ -154,6 +152,15 @@ public:
 
 		hash m_broadcastedHashes[8];
 		uint32_t m_broadcastedHashesIndex;
+
+		// log::Stream wrapper
+		struct SoftwareDisplayName
+		{
+			FORCEINLINE SoftwareDisplayName(SoftwareID id, uint32_t version) : m_id(id), m_version(version) {}
+
+			SoftwareID m_id;
+			uint32_t m_version;
+		};
 	};
 
 	void broadcast(const PoolBlock& block, const PoolBlock* parent);