diff --git a/src/ConnectionManager.cs b/src/ConnectionManager.cs index 9a6300c..b7aba0a 100644 --- a/src/ConnectionManager.cs +++ b/src/ConnectionManager.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Threading; namespace PeerTalk { @@ -37,11 +38,11 @@ public class ConnectionManager public event EventHandler PeerDisconnected; /// - /// Gets the current connections. + /// Gets the current active connections. /// public IEnumerable Connections => connections.Values .SelectMany(c => c) - .Where(c => c.Stream != null && c.Stream.CanRead && c.Stream.CanWrite); + .Where(c => c.IsActive); /// /// Determines if a connection exists to the specified peer. @@ -83,7 +84,7 @@ public bool TryGet(Peer peer, out PeerConnection connection) } connection = conns - .Where(c => c.Stream != null && c.Stream.CanRead && c.Stream.CanWrite) + .Where(c => c.IsActive) .FirstOrDefault(); return connection != null; @@ -125,6 +126,10 @@ public PeerConnection Add(PeerConnection connection) } ); + if (connection.RemotePeer.ConnectedAddress == null) + { + connection.RemotePeer.ConnectedAddress = connection.RemoteAddress; + } connection.Closed += (s, e) => Remove(e); return connection; } @@ -172,6 +177,7 @@ public bool Remove(PeerConnection connection) } else { + connection.RemotePeer.ConnectedAddress = null; PeerDisconnected?.Invoke(this, connection.RemotePeer.Id); } return true; @@ -194,6 +200,7 @@ public bool Remove(MultiHash id) } foreach (var conn in conns) { + conn.RemotePeer.ConnectedAddress = null; conn.Dispose(); } diff --git a/src/PeerConnection.cs b/src/PeerConnection.cs index 0912622..d4c3886 100644 --- a/src/PeerConnection.cs +++ b/src/PeerConnection.cs @@ -62,6 +62,17 @@ public class PeerConnection : IDisposable /// public bool IsIncoming { get; set; } + /// + /// Determines if the connection to the remote can be used. + /// + /// + /// true if the connection is active. + /// + public bool IsActive + { + get { return Stream != null && Stream.CanRead && Stream.CanWrite; } + } + /// /// The duplex stream between the two peers. /// @@ -355,10 +366,6 @@ protected virtual void Dispose(bool disposing) statsStream = null; } } - if (RemotePeer != null && RemotePeer.ConnectedAddress == RemoteAddress) - { - RemotePeer.ConnectedAddress = null; - } SecurityEstablished.TrySetCanceled(); IdentityEstablished.TrySetCanceled(); IdentityEstablished.TrySetCanceled(); diff --git a/src/Swarm.cs b/src/Swarm.cs index 87b68a7..f71574b 100644 --- a/src/Swarm.cs +++ b/src/Swarm.cs @@ -524,6 +524,8 @@ async Task Dial(Peer remote, IEnumerable addrs, Ca } catch (Exception e) { + var attemped = string.Join(", ", possibleAddresses.Select(a => a.ToString())); + log.Warn($"Cannot dial {attemped}", e); throw new Exception($"Cannot dial {remote}.", e); } @@ -593,7 +595,6 @@ async Task DialAsync(Peer remote, MultiAddress addr, Cancellatio } // Build the connection. - remote.ConnectedAddress = addr; var connection = new PeerConnection { IsIncoming = false, @@ -814,8 +815,6 @@ async void OnRemoteConnect(Stream stream, MultiAddress local, MultiAddress remot connection.RemotePeer = RegisterPeer(connection.RemotePeer); connection.RemoteAddress = new MultiAddress($"{remote}/ipfs/{connection.RemotePeer.Id}"); - connection.RemotePeer.ConnectedAddress = connection.RemoteAddress; - var actual = Manager.Add(connection); if (actual == connection) { diff --git a/test/ConnectionManagerTest.cs b/test/ConnectionManagerTest.cs index 1222e19..4ce8624 100644 --- a/test/ConnectionManagerTest.cs +++ b/test/ConnectionManagerTest.cs @@ -113,34 +113,42 @@ public void Add_Duplicate_PeerConnectedAddress() } [TestMethod] - public void Remove_Duplicate_PeerConnectedAddress() + public void Maintains_PeerConnectedAddress() { - var address = "/ip6/::1/tcp/4007"; + var address1 = "/ip4/127.0.0.1/tcp/4007"; + var address2 = "/ip4/127.0.0.2/tcp/4007"; var manager = new ConnectionManager(); - var peer = new Peer { Id = aId, ConnectedAddress = address }; - var a = new PeerConnection { RemotePeer = peer, RemoteAddress = address, Stream = Stream.Null }; - var b = new PeerConnection { RemotePeer = peer, RemoteAddress = address, Stream = Stream.Null }; + var peer = new Peer { Id = aId }; + var a = new PeerConnection { RemotePeer = peer, RemoteAddress = address1, Stream = Stream.Null }; + var b = new PeerConnection { RemotePeer = peer, RemoteAddress = address2, Stream = Stream.Null }; Assert.AreSame(a, manager.Add(a)); Assert.IsTrue(manager.IsConnected(peer)); Assert.AreEqual(1, manager.Connections.Count()); Assert.IsNotNull(a.Stream); - Assert.AreEqual(address, peer.ConnectedAddress); + Assert.AreEqual(address1, peer.ConnectedAddress); Assert.AreSame(b, manager.Add(b)); Assert.IsTrue(manager.IsConnected(peer)); Assert.AreEqual(2, manager.Connections.Count()); Assert.IsNotNull(a.Stream); Assert.IsNotNull(b.Stream); - Assert.AreEqual(address, peer.ConnectedAddress); + Assert.AreEqual(address1, peer.ConnectedAddress); - Assert.IsTrue(manager.Remove(b)); + Assert.IsTrue(manager.Remove(a)); Assert.IsTrue(manager.IsConnected(peer)); Assert.AreEqual(1, manager.Connections.Count()); - Assert.IsNotNull(a.Stream); + Assert.IsNull(a.Stream); + Assert.IsNotNull(b.Stream); + Assert.AreEqual(address2, peer.ConnectedAddress); + + Assert.IsTrue(manager.Remove(b)); + Assert.IsFalse(manager.IsConnected(peer)); + Assert.AreEqual(0, manager.Connections.Count()); + Assert.IsNull(a.Stream); Assert.IsNull(b.Stream); - Assert.AreEqual(address, peer.ConnectedAddress); + Assert.IsNull(peer.ConnectedAddress); } [TestMethod] diff --git a/test/PeerConnectionTest.cs b/test/PeerConnectionTest.cs index 179fb0a..e342c0b 100644 --- a/test/PeerConnectionTest.cs +++ b/test/PeerConnectionTest.cs @@ -22,14 +22,17 @@ public void Disposing() { ++closeCount; }; + Assert.IsTrue(connection.IsActive); Assert.IsNotNull(connection.Stream); connection.Dispose(); + Assert.IsFalse(connection.IsActive); Assert.IsNull(connection.Stream); // Can be disposed multiple times. connection.Dispose(); + Assert.IsFalse(connection.IsActive); Assert.AreEqual(1, closeCount); }