Skip to content
Permalink
Browse files

Merge pull request #240 from longfin/bugfix/nat-to-nat

Fix relaying bug with NAT
  • Loading branch information...
longfin committed May 15, 2019
2 parents 08ae1a9 + f4a7b25 commit 8b7598f142cb62ce2f30643d920cc242766d14b0
Showing with 60 additions and 21 deletions.
  1. +3 −0 CHANGES.md
  2. +1 −1 Libplanet.Tests/Net/PeerTest.cs
  3. +1 −1 Libplanet.Tests/Net/SwarmTest.cs
  4. +26 −12 Libplanet/Net/Peer.cs
  5. +29 −7 Libplanet/Net/Swarm.cs
@@ -117,6 +117,8 @@ To be released.
[[#217]]
- Improved concurrency of `BlockChain<T>.Append()` method by removing
unnecessary race conditions. [[#217]]
- Fixed a bug that `Swarm` could not properly communicate with `Peer` behind
NAT. [[#240]]

[Ethereum Homestead algorithm]: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md
[#31]: https://github.com/planetarium/libplanet/issues/31
@@ -144,6 +146,7 @@ To be released.
[#232]: https://github.com/planetarium/libplanet/pull/232
[#234]: https://github.com/planetarium/libplanet/pull/234
[#236]: https://github.com/planetarium/libplanet/pull/236
[#240]: https://github.com/planetarium/libplanet/pull/240


Version 0.2.2
@@ -18,7 +18,7 @@ public void Serialize()
"7ca8dbad5e1c8c9b130a9d39171a44134"
));
var endPoint = new DnsEndPoint("0.0.0.0", 1234);
var peer = new Peer(key, endPoint, 1);
var peer = new Peer(key, endPoint, 1, IPAddress.IPv6Loopback);
var formatter = new BinaryFormatter();
using (var stream = new MemoryStream())
{
@@ -713,7 +713,7 @@ public async Task AsPeerThrowSwarmExceptionWhenUnbound()
}

[Trait("RequireTurnServer", "true")]
[FactOnlyTurnAvailable]
[FactOnlyTurnAvailable(Timeout = Timeout)]
public async Task ExchangeWithIceServer()
{
Uri turnUrl = FactOnlyTurnAvailable.TurnUri;
@@ -25,20 +25,25 @@ public class Peer : ISerializable
/// <param name="appProtocolVersion">An application protocol version
/// that the <see cref="Peer"/> is using.</param>
public Peer(
PublicKey publicKey, DnsEndPoint endPoint, int appProtocolVersion)
PublicKey publicKey,
DnsEndPoint endPoint,
int appProtocolVersion)
: this(publicKey, endPoint, appProtocolVersion, null)
{
if (publicKey == null)
{
throw new ArgumentNullException(nameof(publicKey));
}
else if (endPoint == null)
{
throw new ArgumentNullException(nameof(endPoint));
}
}

PublicKey = publicKey;
EndPoint = endPoint;
internal Peer(
PublicKey publicKey,
DnsEndPoint endPoint,
int appProtocolVersion,
IPAddress publicIPAddress)
{
PublicKey = publicKey ??
throw new ArgumentNullException(nameof(publicKey));
EndPoint = endPoint ??
throw new ArgumentNullException(nameof(endPoint));
AppProtocolVersion = appProtocolVersion;
PublicIPAddress = publicIPAddress;
}

protected Peer(SerializationInfo info, StreamingContext context)
@@ -48,6 +53,11 @@ protected Peer(SerializationInfo info, StreamingContext context)
info.GetString("end_point_host"),
info.GetInt32("end_point_port"));
AppProtocolVersion = info.GetInt32("app_protocol_version");
string addressStr = info.GetString("public_ip_address");
if (addressStr != null)
{
PublicIPAddress = IPAddress.Parse(addressStr);
}
}

/// <summary>
@@ -71,14 +81,17 @@ protected Peer(SerializationInfo info, StreamingContext context)
[Pure]
public int AppProtocolVersion { get; }

/// <summary>The peer's address which is derviced from
/// <summary>The peer's address which is derived from
/// its <see cref="PublicKey"/>.
/// </summary>
/// <seealso cref="PublicKey"/>
[IgnoreDuringEquals]
[Pure]
public Address Address => new Address(PublicKey);

[Pure]
internal IPAddress PublicIPAddress { get; }

/// <inheritdoc/>
public void GetObjectData(
SerializationInfo info,
@@ -89,6 +102,7 @@ StreamingContext context
info.AddValue("end_point_host", EndPoint.Host);
info.AddValue("end_point_port", EndPoint.Port);
info.AddValue("app_protocol_version", AppProtocolVersion);
info.AddValue("public_ip_address", PublicIPAddress?.ToString());
}

/// <inheritdoc/>
@@ -63,6 +63,7 @@ public class Swarm : ICollection<Peer>
private int? _listenPort;
private TurnClient _turnClient;
private CancellationTokenSource _workerCancellationTokenSource;
private IPAddress _publicIPAddress;

public Swarm(
PrivateKey privateKey,
@@ -184,7 +185,11 @@ public class Swarm : ICollection<Peer>

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

@@ -470,8 +475,18 @@ IEnumerator IEnumerable.GetEnumerator()

_logger.Information($"Listen on {_listenPort}");

bool behindNAT =
_turnClient != null && await _turnClient.IsBehindNAT();
var behindNAT = false;

if (!(_turnClient is null))
{
_publicIPAddress = (await _turnClient.GetMappedAddressAsync())
.Address;

if (await _turnClient.IsBehindNAT())
{
behindNAT = true;
}
}

if (behindNAT)
{
@@ -1734,15 +1749,22 @@ private string ToNetMQAddress(Peer peer)

private async Task CreatePermission(Peer peer)
{
var peerHost = peer.EndPoint.Host;
IPAddress[] ips;
if (IPAddress.TryParse(peerHost, out IPAddress asIp))
if (peer.PublicIPAddress is null)
{
ips = new[] { asIp };
string peerHost = peer.EndPoint.Host;
if (IPAddress.TryParse(peerHost, out IPAddress asIp))
{
ips = new[] { asIp };
}
else
{
ips = await Dns.GetHostAddressesAsync(peerHost);
}
}
else
{
ips = await Dns.GetHostAddressesAsync(peerHost);
ips = new[] { peer.PublicIPAddress };
}

foreach (IPAddress ip in ips)

0 comments on commit 8b7598f

Please sign in to comment.
You can’t perform that action at this time.