Skip to content

Commit

Permalink
Peer.EndPoints to Peer.EndPoint
Browse files Browse the repository at this point in the history
closes #126
  • Loading branch information
longfin committed Mar 11, 2019
1 parent b662da4 commit b3cdd49
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 168 deletions.
2 changes: 1 addition & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Version 0.2.0

To be released.

- The type of `Peer.Urls` property is changed from `Uri` to `IPEndPoint`.
- `Peer.Urls` is changed to `Peer.EndPoint` represented as single `IPEndPoint`.
- `Address` and `TxId` are now serializable.


Expand Down
8 changes: 4 additions & 4 deletions Libplanet.Tests/Net/PeerSetDeltaTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,25 @@ namespace Libplanet.Tests.Net
public class PeerSetDeltaTest
{
[Fact]
public void CanBeSerialized()
public void Serialize()
{
var peerSetDelta = new PeerSetDelta(
new Peer(
new PrivateKey().PublicKey,
new[] { new IPEndPoint(IPAddress.Parse("0.0.0.0"), 1234) }
new IPEndPoint(IPAddress.Parse("0.0.0.0"), 1234)
),
DateTimeOffset.UtcNow,
new[]
{
new Peer(
new PrivateKey().PublicKey,
new[] { new IPEndPoint(IPAddress.Parse("1.2.3.4"), 1234) }),
new IPEndPoint(IPAddress.Parse("1.2.3.4"), 1234)),
}.ToImmutableHashSet(),
new[]
{
new Peer(
new PrivateKey().PublicKey,
new[] { new IPEndPoint(IPAddress.Parse("2.3.4.5"), 1234) }),
new IPEndPoint(IPAddress.Parse("2.3.4.5"), 1234)),
}.ToImmutableHashSet(),
null
);
Expand Down
73 changes: 8 additions & 65 deletions Libplanet.Tests/Net/PeerTest.cs
Original file line number Diff line number Diff line change
@@ -1,81 +1,24 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Net;
using System.Runtime.Serialization.Formatters.Binary;
using Libplanet.Crypto;
using Libplanet.Net;
using Libplanet.Serialization;
using Xunit;

namespace Libplanet.Tests.Net
{
public class PeerTest
{
private static PublicKey _samplePublicKey = new PublicKey(
ByteUtil.ParseHex(
"038f92e8098c897c2a9ae3226eb6337eb" +
"7ca8dbad5e1c8c9b130a9d39171a44134"
)
);

private static IPEndPoint[] _sampleEndPoints = new IPEndPoint[]
{
new IPEndPoint(IPAddress.Parse("0.0.0.0"), 1234),
new IPEndPoint(IPAddress.Parse("1.2.3.4"), 1234),
new IPEndPoint(IPAddress.Parse("2.3.4.5"), 1234),
};

[Fact]
public void ConstructorWithImmutableList()
{
Assert.Throws<ArgumentNullException>(
() => new Peer(_samplePublicKey, null)
);
var peer = new Peer(
_samplePublicKey,
_sampleEndPoints.ToImmutableList()
);
Assert.Equal(_samplePublicKey, peer.PublicKey);
Assert.Equal(_sampleEndPoints, peer.EndPoints);
}

[Fact]
public void ConstructorWithEnumerable()
{
Assert.Throws<ArgumentNullException>(
() => new Peer(_samplePublicKey, (IEnumerable<IPEndPoint>)null)
);
var peer = new Peer(_samplePublicKey, _sampleEndPoints);
Assert.Equal(_samplePublicKey, peer.PublicKey);
Assert.Equal(_sampleEndPoints, peer.EndPoints);
}

[Fact]
public void AddUrl()
{
var peer = new Peer(_samplePublicKey, _sampleEndPoints);
Assert.Equal(_samplePublicKey, peer.PublicKey);
Assert.Equal(
new IPEndPoint[]
{
new IPEndPoint(IPAddress.Parse("0.0.0.0"), 1234),
new IPEndPoint(IPAddress.Parse("1.2.3.4"), 1234),
new IPEndPoint(IPAddress.Parse("2.3.4.5"), 1234),
new IPEndPoint(IPAddress.Parse("3.4.5.6"), 1234),
},
peer.AddEndPoint(new IPEndPoint(IPAddress.Parse("3.4.5.6"), 1234)).EndPoints
);
}

[Fact]
public void CanBeSerialized()
public void Serialize()
{
var peer = new Peer(
_samplePublicKey,
_sampleEndPoints.ToImmutableList()
);
var key = new PublicKey(
ByteUtil.ParseHex(
"038f92e8098c897c2a9ae3226eb6337eb" +
"7ca8dbad5e1c8c9b130a9d39171a44134"
));
var endPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 1234);
var peer = new Peer(key, endPoint);
var formatter = new BinaryFormatter();
using (var stream = new MemoryStream())
{
Expand Down
41 changes: 32 additions & 9 deletions Libplanet.Tests/Net/SwarmTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -263,12 +263,18 @@ public async Task CanExchangePeer()
}

[Fact]
public void WorksAsCollection()
public async Task WorksAsCollection()
{
Swarm a = _swarms[0];
Swarm b = _swarms[1];
Swarm c = _swarms[2];

// Obtaining swarm's endpoint...
await Task.WhenAll(
StartAsync(a, _blockchains[0]),
StartAsync(b, _blockchains[1]),
StartAsync(c, _blockchains[2]));

Assert.Empty(a);
Assert.Empty(b);
Assert.Empty(c);
Expand Down Expand Up @@ -300,14 +306,23 @@ public void WorksAsCollection()
}

[Fact]
public void CanBeComparedProperly()
public void BeComparedProperly()
{
var pk1 = new PrivateKey();
var pk2 = new PrivateKey();
var a = new Swarm(pk1);
var b = new Swarm(pk1, createdAt: a.LastDistributed);
var c = new Swarm(pk2);
var u1 = new Uri($"inproc://swarmtest.t");
var a = new Swarm(
pk1,
ipAddress: IPAddress.Parse("0.0.0.0"),
listenPort: 5555);
var b = new Swarm(
pk1,
ipAddress: IPAddress.Parse("0.0.0.0"),
listenPort: 5555,
createdAt: a.LastDistributed);
var c = new Swarm(
pk2,
ipAddress: IPAddress.Parse("0.0.0.0"),
listenPort: 5555);

Assert.Equal(a, b);
Assert.NotEqual(a, c);
Expand Down Expand Up @@ -580,9 +595,7 @@ public void CanResolveEndPoint()
listenPort: 5678);

Assert.Equal(expected, s.EndPoint);
Assert.Equal(
new[] { expected },
s.AsPeer.EndPoints);
Assert.Equal(expected, s.AsPeer.EndPoint);
}

[Fact]
Expand All @@ -598,6 +611,16 @@ public async Task CanStopGracefullyWhileStarting()
await Task.WhenAll(a.StopAsync(), t);
}

[Fact]
public async Task AsPeerThrowSwarmExceptionWhenUnbound()
{
Swarm swarm = new Swarm(new PrivateKey());
Assert.Throws<SwarmException>(() => swarm.AsPeer);

await StartAsync(swarm, _blockchains[0]);
Assert.Equal(swarm.EndPoint, swarm.AsPeer.EndPoint);
}

private async Task<Task> StartAsync<T>(
Swarm swarm,
BlockChain<T> blockChain,
Expand Down
42 changes: 8 additions & 34 deletions Libplanet/Net/Peer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,41 +15,25 @@ namespace Libplanet.Net
[GeneratedEquality]
public partial class Peer : ISerializable
{
public Peer(PublicKey publicKey, IImmutableList<IPEndPoint> endPoints)
public Peer(PublicKey publicKey, IPEndPoint endPoint)
{
if (publicKey == null)
{
throw new ArgumentNullException(nameof(publicKey));
}
else if (endPoints == null)
else if (endPoint == null)
{
throw new ArgumentNullException(nameof(endPoints));
throw new ArgumentNullException(nameof(endPoint));
}

PublicKey = publicKey;
EndPoints = endPoints;
}

public Peer(PublicKey publicKey, IEnumerable<IPEndPoint> endPoints)
: this(publicKey, endPoints.ToImmutableArray())
{
EndPoint = endPoint;
}

protected Peer(SerializationInfo info, StreamingContext context)
{
PublicKey = new PublicKey(info.GetValue<byte[]>("public_key"));
var points = info.GetValue<List<string>>("end_points");
var endPoints = new List<IPEndPoint>();
foreach (var point in points)
{
var split = point.Split(':');
var endPoint = new IPEndPoint(
IPAddress.Parse(split[0]),
int.Parse(split[1]));
endPoints.Add(endPoint);
}

EndPoints = endPoints.ToImmutableList();
EndPoint = info.GetValue<IPEndPoint>("end_point");
}

[EqualityKey]
Expand All @@ -58,33 +42,23 @@ protected Peer(SerializationInfo info, StreamingContext context)

[EqualityKey]
[Pure]
public IImmutableList<IPEndPoint> EndPoints { get; }
public IPEndPoint EndPoint { get; }

[Pure]
public Address Address => new Address(PublicKey);

[Pure]
public Peer AddEndPoint(IPEndPoint endPoint) =>
new Peer(PublicKey, EndPoints.Add(endPoint));

public void GetObjectData(
SerializationInfo info,
StreamingContext context
)
{
info.AddValue("public_key", PublicKey.Format(true));
info.AddValue(
"end_points",
EndPoints.Select(e => e.ToString()).ToList());
info.AddValue("end_point", EndPoint);
}

public override string ToString()
{
var endPointStrings = EndPoints.Select(e => e.ToString());
return string.Join(
",",
new[] { Address.ToString() }.Concat(endPointStrings)
);
return $"{Address}.{EndPoint}";
}
}
}
84 changes: 29 additions & 55 deletions Libplanet/Net/Swarm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,11 @@ public IPEndPoint EndPoint
[Uno.EqualityKey]
public Address Address => _privateKey.PublicKey.ToAddress();

public Peer AsPeer => new Peer(
_privateKey.PublicKey,
EndPoint != null ? new[] { EndPoint } : new IPEndPoint[] { }
);
public Peer AsPeer =>
EndPoint != null
? new Peer(_privateKey.PublicKey, EndPoint)
: throw new SwarmException(
"Can't translate unbound Swarm to Peer.");

[Uno.EqualityIgnore]
public AsyncAutoResetEvent DeltaReceived { get; }
Expand Down Expand Up @@ -1260,58 +1261,33 @@ private async Task<Peer> DialPeerAsync(
Peer peer, CancellationToken cancellationToken)
{
Peer original = peer;
var connected = false;

// Peer can have more than 2 Url due to NAT and so on.
// Therefore, DialPeerAsync () checks the accessible URLs
// and puts them at the front.
foreach (var (endPoint, i) in peer.EndPoints.Select((endPoint, i) =>
(endPoint, i)))
var dealer = new DealerSocket();
dealer.Options.Identity =
_privateKey.PublicKey.ToAddress().ToByteArray();
try
{
var dealer = new DealerSocket();
dealer.Options.Identity =
_privateKey.PublicKey.ToAddress().ToByteArray();
try
{
_logger.Debug($"Trying to DialAsync({endPoint})...");
await DialAsync(
ToNetMQAddress(peer),
dealer,
cancellationToken);
_logger.Debug($"DialAsync({endPoint}) is complete.");
}
catch (IOException e)
{
_logger.Error(
e,
$"IOException occured in DialAsync ({endPoint})."
);
dealer.Dispose();
continue;
}
catch (TimeoutException e)
{
_logger.Error(
e,
$"TimeoutException occured in DialAsync ({endPoint})."
);
dealer.Dispose();
continue;
}

if (i > 0)
{
peer = new Peer(peer.PublicKey, peer.EndPoints.Skip(i));
}

_logger.Debug($"Trying to DialAsync({peer.EndPoint})...");
await DialAsync(
ToNetMQAddress(peer),
dealer,
cancellationToken);
_logger.Debug($"DialAsync({peer.EndPoint}) is complete.");
_dealers[peer.Address] = dealer;
connected = true;
break;
}

if (!connected)
catch (IOException e)
{
_logger.Error(
e,
$"IOException occured in DialAsync ({peer.EndPoint}).");
dealer.Dispose();
}
catch (TimeoutException e)
{
throw new IOException($"not reachable at all to {original}");
_logger.Error(
e,
$"TimeoutException occured in DialAsync ({peer.EndPoint})."
);
dealer.Dispose();
}

return peer;
Expand Down Expand Up @@ -1418,9 +1394,7 @@ private string ToNetMQAddress(Peer peer)
throw new ArgumentNullException(nameof(peer));
}

// See DialPeerAsync().
var endPoint = peer.EndPoints.FirstOrDefault();
return $"tcp://{endPoint}";
return $"tcp://{peer.EndPoint}";
}
}
}

0 comments on commit b3cdd49

Please sign in to comment.