diff --git a/CHANGES.md b/CHANGES.md index 9186837458e..8cbb875f925 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,8 @@ To be released. - Added `LiteDBStore` backend that uses [LiteDB] under the hood. [[#269]] - All `*Async()` methods belonging to `TurnClient` class became to have `cancellationToken` option. [[#287]] + - Added a version-less `Peer` constructor to create a `Peer` whose version + is unknown. ### Behavioral changes diff --git a/Libplanet.Tests/Net/PeerTest.cs b/Libplanet.Tests/Net/PeerTest.cs index 4f2b5a3bc51..ee19e0088bb 100644 --- a/Libplanet.Tests/Net/PeerTest.cs +++ b/Libplanet.Tests/Net/PeerTest.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.IO; using System.Net; using System.Runtime.Serialization.Formatters.Binary; @@ -9,16 +10,62 @@ namespace Libplanet.Tests.Net { public class PeerTest { - [Fact] - public void Serialize() + public static IEnumerable GetPeers() + { + yield return new object[] + { + new Peer( + new PublicKey(new byte[] + { + 0x04, 0xb5, 0xa2, 0x4a, 0xa2, 0x11, 0x27, 0x20, 0x42, 0x3b, + 0xad, 0x39, 0xa0, 0x20, 0x51, 0x82, 0x37, 0x9d, 0x6f, 0x2b, + 0x33, 0xe3, 0x48, 0x7c, 0x9a, 0xb6, 0xcc, 0x8f, 0xc4, 0x96, + 0xf8, 0xa5, 0x48, 0x34, 0x40, 0xef, 0xbb, 0xef, 0x06, 0x57, + 0xac, 0x2e, 0xf6, 0xc6, 0xee, 0x05, 0xdb, 0x06, 0xa9, 0x45, + 0x32, 0xfd, 0xa7, 0xdd, 0xc4, 0x4a, 0x16, 0x95, 0xe5, 0xce, + 0x1a, 0x3d, 0x3c, 0x76, 0xdb, + }), + new DnsEndPoint("0.0.0.0", 1234), + 1, + IPAddress.IPv6Loopback), + }; + yield return new object[] + { + new Peer( + new PublicKey(new byte[] + { + 0x04, 0xb5, 0xa2, 0x4a, 0xa2, 0x11, 0x27, 0x20, 0x42, 0x3b, + 0xad, 0x39, 0xa0, 0x20, 0x51, 0x82, 0x37, 0x9d, 0x6f, 0x2b, + 0x33, 0xe3, 0x48, 0x7c, 0x9a, 0xb6, 0xcc, 0x8f, 0xc4, 0x96, + 0xf8, 0xa5, 0x48, 0x34, 0x40, 0xef, 0xbb, 0xef, 0x06, 0x57, + 0xac, 0x2e, 0xf6, 0xc6, 0xee, 0x05, 0xdb, 0x06, 0xa9, 0x45, + 0x32, 0xfd, 0xa7, 0xdd, 0xc4, 0x4a, 0x16, 0x95, 0xe5, 0xce, + 0x1a, 0x3d, 0x3c, 0x76, 0xdb, + }), + new DnsEndPoint("0.0.0.0", 1234), + 1), + }; + yield return new object[] + { + new Peer( + new PublicKey(new byte[] + { + 0x04, 0xb5, 0xa2, 0x4a, 0xa2, 0x11, 0x27, 0x20, 0x42, 0x3b, + 0xad, 0x39, 0xa0, 0x20, 0x51, 0x82, 0x37, 0x9d, 0x6f, 0x2b, + 0x33, 0xe3, 0x48, 0x7c, 0x9a, 0xb6, 0xcc, 0x8f, 0xc4, 0x96, + 0xf8, 0xa5, 0x48, 0x34, 0x40, 0xef, 0xbb, 0xef, 0x06, 0x57, + 0xac, 0x2e, 0xf6, 0xc6, 0xee, 0x05, 0xdb, 0x06, 0xa9, 0x45, + 0x32, 0xfd, 0xa7, 0xdd, 0xc4, 0x4a, 0x16, 0x95, 0xe5, 0xce, + 0x1a, 0x3d, 0x3c, 0x76, 0xdb, + }), + new DnsEndPoint("0.0.0.0", 1234)), + }; + } + + [Theory] + [MemberData(nameof(GetPeers))] + public void Serialize(Peer peer) { - var key = new PublicKey( - ByteUtil.ParseHex( - "038f92e8098c897c2a9ae3226eb6337eb" + - "7ca8dbad5e1c8c9b130a9d39171a44134" - )); - var endPoint = new DnsEndPoint("0.0.0.0", 1234); - var peer = new Peer(key, endPoint, 1, IPAddress.IPv6Loopback); var formatter = new BinaryFormatter(); using (var stream = new MemoryStream()) { @@ -29,5 +76,20 @@ public void Serialize() Assert.Equal(peer, deserialized); } } + + [Fact] + public void WithAppProtocolVersion() + { + var peerWithoutVersion = new Peer( + new PrivateKey().PublicKey, + new DnsEndPoint("0.0.0.0", 1234)); + Peer peerWithVersion = peerWithoutVersion.WithAppProtocolVersion(42); + var expected = new Peer( + peerWithoutVersion.PublicKey, + peerWithoutVersion.EndPoint, + 42 + ); + Assert.Equal(expected, peerWithVersion); + } } } diff --git a/Libplanet/Net/Peer.cs b/Libplanet/Net/Peer.cs index fcac7599e5c..7503f6d99f3 100644 --- a/Libplanet/Net/Peer.cs +++ b/Libplanet/Net/Peer.cs @@ -15,6 +15,20 @@ namespace Libplanet.Net [Equals] public class Peer : ISerializable { + /// + /// Initializes a new instance of the class. + /// + /// A of the + /// . + /// A consisting of the + /// host and port of the . + public Peer( + PublicKey publicKey, + DnsEndPoint endPoint) + : this(publicKey, endPoint, default(int?), null) + { + } + /// /// Initializes a new instance of the class. /// @@ -27,7 +41,7 @@ public class Peer : ISerializable public Peer( PublicKey publicKey, DnsEndPoint endPoint, - int appProtocolVersion) + int? appProtocolVersion) : this(publicKey, endPoint, appProtocolVersion, null) { } @@ -35,7 +49,7 @@ public class Peer : ISerializable internal Peer( PublicKey publicKey, DnsEndPoint endPoint, - int appProtocolVersion, + int? appProtocolVersion, IPAddress publicIPAddress) { PublicKey = publicKey ?? @@ -52,7 +66,8 @@ protected Peer(SerializationInfo info, StreamingContext context) EndPoint = new DnsEndPoint( info.GetString("end_point_host"), info.GetInt32("end_point_port")); - AppProtocolVersion = info.GetInt32("app_protocol_version"); + AppProtocolVersion = + info.GetValueOrDefault("app_protocol_version", null); string addressStr = info.GetString("public_ip_address"); if (addressStr != null) { @@ -79,7 +94,7 @@ protected Peer(SerializationInfo info, StreamingContext context) /// [IgnoreDuringEquals] [Pure] - public int AppProtocolVersion { get; } + public int? AppProtocolVersion { get; } /// The peer's address which is derived from /// its . @@ -110,5 +125,14 @@ public override string ToString() { return $"{Address}.{EndPoint}.{AppProtocolVersion}"; } + + internal Peer WithAppProtocolVersion(int appProtocolVersion) + { + return new Peer( + PublicKey, + EndPoint, + appProtocolVersion, + PublicIPAddress); + } } } diff --git a/Libplanet/Net/Swarm.cs b/Libplanet/Net/Swarm.cs index 084c2ab26f3..3320db73896 100644 --- a/Libplanet/Net/Swarm.cs +++ b/Libplanet/Net/Swarm.cs @@ -287,11 +287,12 @@ private set try { _logger.Debug($"Trying to DialPeerAsync({peer})..."); - await DialPeerAsync(peer, cancellationToken); + Pong pong = await DialPeerAsync(peer, cancellationToken); _logger.Debug($"DialPeerAsync({peer}) is complete."); - _peers[peer] = timestamp.Value; - addedPeers.Add(peer); + Peer peerWithVersion = peer.WithAppProtocolVersion(pong.AppProtocolVersion); + _peers[peerWithVersion] = timestamp.Value; + addedPeers.Add(peerWithVersion); } catch (IOException e) { @@ -1413,12 +1414,13 @@ CancellationToken cancellationToken if (IsUnknownPeer(sender)) { _logger.Debug("The sender of delta is unknown."); - if (IsDifferentProtocolVersion(sender)) + if (IsDifferentProtocolVersion(sender) && + sender.AppProtocolVersion is int senderVersion) { var args = new DifferentProtocolVersionEventArgs { ExpectedVersion = _appProtocolVersion, - ActualVersion = sender.AppProtocolVersion, + ActualVersion = senderVersion, }; DifferentVersionPeerEncountered?.Invoke(this, args); return;