diff --git a/plugins/RpcServer/RpcServer.Node.cs b/plugins/RpcServer/RpcServer.Node.cs index 20f105d34..0d5bb7702 100644 --- a/plugins/RpcServer/RpcServer.Node.cs +++ b/plugins/RpcServer/RpcServer.Node.cs @@ -123,7 +123,7 @@ private static JObject GetRelayResult(VerifyResult reason, UInt256 hash) /// "result": { /// "tcpport": 10333, // The TCP port, /// "nonce": 1, // The nonce, - /// "useragent": "The user agent", + /// "useragent": "/Neo:3.10.2/", // Node assembly version in the existing useragent field, /// "rpc": { /// "maxiteratorresultitems": 100, // The maximum number of items in the iterator result, /// "sessionenabled": false // Whether session is enabled, @@ -152,7 +152,8 @@ protected internal virtual JToken GetVersion() JObject json = new(); json["tcpport"] = localNode.ListenerTcpPort; json["nonce"] = LocalNode.Nonce; - json["useragent"] = LocalNode.UserAgent; + var nodeVersion = typeof(RpcServer).Assembly.GetName().Version?.ToString(3) ?? "0.0.0"; + json["useragent"] = UserAgentWithVersion(LocalNode.UserAgent, nodeVersion); // rpc settings JObject rpc = new(); rpc["maxiteratorresultitems"] = settings.MaxIteratorResultItems; @@ -183,6 +184,19 @@ protected internal virtual JToken GetVersion() return json; } + /// + /// Keeps the P2P useragent product name and replaces the version with . + /// /Neo:3.10.1/ plus 3.10.2 becomes /Neo:3.10.2/. + /// + internal static string UserAgentWithVersion(string userAgent, string version) + { + var colon = userAgent.IndexOf(':'); + var slash = userAgent.LastIndexOf('/'); + if (colon >= 0 && slash > colon) + return string.Concat(userAgent.AsSpan(0, colon + 1), version, userAgent.AsSpan(slash)); + return $"/Neo:{version}/"; + } + /// /// Removes a specified prefix from a string if it exists. /// diff --git a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Node.cs b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Node.cs index 8ba40aa09..961650f74 100644 --- a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Node.cs +++ b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Node.cs @@ -117,6 +117,17 @@ public void TestGetVersion() Assert.IsTrue(json.ContainsProperty("tcpport")); Assert.IsTrue(json.ContainsProperty("nonce")); Assert.IsTrue(json.ContainsProperty("useragent")); + Assert.IsFalse(json.ContainsProperty("version")); + var nodeVersion = _rpcServer.GetType().Assembly.GetName().Version?.ToString(3) ?? "0.0.0"; + Assert.AreEqual(RpcServer.UserAgentWithVersion(LocalNode.UserAgent, nodeVersion), json["useragent"]!.AsString()); + Assert.Contains($":{nodeVersion}/", json["useragent"]!.AsString()); + + Assert.IsTrue(json.ContainsProperty("rpc")); + var rpc = (JObject)json["rpc"]!; + Assert.IsTrue(rpc.ContainsProperty("maxiteratorresultitems")); + Assert.IsTrue(rpc.ContainsProperty("sessionenabled")); + Assert.AreEqual(_rpcServerSettings.MaxIteratorResultItems, rpc["maxiteratorresultitems"]!.AsNumber()); + Assert.AreEqual(_rpcServerSettings.SessionEnabled, rpc["sessionenabled"]!.AsBoolean()); Assert.IsTrue(json.ContainsProperty("protocol")); var protocol = (JObject)json["protocol"]; @@ -132,6 +143,15 @@ public void TestGetVersion() Assert.IsTrue(protocol.ContainsProperty("seedlist")); } + [TestMethod] + public void TestUserAgentWithVersion_ReplacesVersionKeepsProduct() + { + Assert.AreEqual("/Neo:3.10.2/", RpcServer.UserAgentWithVersion("/Neo:3.10.1/", "3.10.2")); + Assert.AreEqual("/MyNode:3.10.2/", RpcServer.UserAgentWithVersion("/MyNode:1.0.0/", "3.10.2")); + Assert.AreEqual("/Neo:3.10.2/", RpcServer.UserAgentWithVersion("not-a-ua", "3.10.2")); + Assert.AreEqual("/Neo:3.10.2/", RpcServer.UserAgentWithVersion(string.Empty, "3.10.2")); + } + [TestMethod] public void TestGetVersion_HardforksStructure() {