예제 #1
0
        /// <summary>
        ///   Called when the swarm has a new peer.
        /// </summary>
        /// <param name="sender">
        ///   The swarm of peers.
        /// </param>
        /// <param name="peer">
        ///   The peer that was discovered.
        /// </param>
        /// <remarks>
        ///   If the <see cref="MinConnections"/> is not reached, then the
        ///   <paramref name="peer"/> is dialed.
        /// </remarks>
        void OnPeerDiscovered(object sender, Peer peer)
        {
            var n = swarm.Manager.Connections.Count() + pendingConnects;

            if (swarm.IsRunning && n < MinConnections)
            {
                Interlocked.Increment(ref pendingConnects);
                Task.Run(async() =>
                {
                    log.Debug($"Dialing new {peer}");
                    try
                    {
                        await swarm.ConnectAsync(peer).ConfigureAwait(false);
                    }
                    catch (Exception)
                    {
                        log.Warn($"Failed to dial {peer}");
                    }
                    finally
                    {
                        Interlocked.Decrement(ref pendingConnects);
                    }
                });
            }
        }
예제 #2
0
        public async Task Connect_CancelsOnStop()
        {
            var swarm = new Swarm {
                LocalPeer = self
            };
            var venus = new Peer
            {
                Id        = "QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
                Addresses = new MultiAddress[]
                {
                    "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",            // mars.i.ipfs.io
                }
            };

            await swarm.StartAsync();

            var a = swarm.ConnectAsync(venus);

            Assert.IsFalse(a.IsCanceled || a.IsFaulted);

            await swarm.StopAsync();

            var endTime = DateTime.Now.AddSeconds(3);

            while (!a.IsCanceled && !a.IsFaulted)
            {
                if (DateTime.Now > endTime)
                {
                    Assert.Fail("swarm did not cancel pending connection.");
                }
                await Task.Delay(100);
            }
            Assert.IsTrue(a.IsCanceled || a.IsFaulted);
        }
예제 #3
0
        public async Task Connect_IsPending()
        {
            var swarm = new Swarm {
                LocalPeer = self
            };
            var venus = new Peer
            {
                Id        = "QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
                Addresses = new MultiAddress[]
                {
                    "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",            // mars.i.ipfs.io
                }
            };

            await swarm.StartAsync();

            try
            {
                Assert.IsFalse(swarm.HasPendingConnection(venus));

                var a = swarm.ConnectAsync(venus);
                Assert.IsTrue(swarm.HasPendingConnection(venus));
            }
            finally
            {
                await swarm.StopAsync();
            }
        }
예제 #4
0
        public async Task ConnectionEstablished()
        {
            var peerB = new Peer
            {
                AgentVersion = "peerB",
                Id           = "QmdpwjdB94eNm2Lcvp9JqoCxswo3AKQqjLuNZyLixmCM1h",
                PublicKey    = "CAASXjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDlTSgVLprWaXfmxDr92DJE1FP0wOexhulPqXSTsNh5ot6j+UiuMgwb0shSPKzLx9AuTolCGhnwpTBYHVhFoBErAgMBAAE="
            };
            var swarmB = new Swarm {
                LocalPeer = peerB
            };
            var swarmBConnections = 0;

            swarmB.ConnectionEstablished += (s, e) =>
            {
                ++swarmBConnections;
            };
            await swarmB.StartAsync();

            var peerBAddress = await swarmB.StartListeningAsync("/ip4/127.0.0.1/tcp/0");

            var swarm = new Swarm {
                LocalPeer = self
            };
            var swarmConnections = 0;

            swarm.ConnectionEstablished += (s, e) =>
            {
                ++swarmConnections;
            };
            await swarm.StartAsync();

            try
            {
                var remotePeer = await swarm.ConnectAsync(peerBAddress);

                Assert.AreEqual(1, swarmConnections);

                // wait for swarmB to settle
                var endTime = DateTime.Now.AddSeconds(3);
                while (true)
                {
                    if (DateTime.Now > endTime)
                    {
                        Assert.Fail("swarmB did not raise event.");
                    }
                    if (swarmBConnections == 1)
                    {
                        break;
                    }
                    await Task.Delay(100);
                }
            }
            finally
            {
                await swarm.StopAsync();

                await swarmB.StopAsync();
            }
        }
예제 #5
0
        public void Connect_Failure_Event()
        {
            var          remoteId      = "QmXFX2P5ammdmXQgfqGkfswtEVFsZUJ5KeHRXQYCTdiTAb";
            MultiAddress remoteAddress = $"/ip4/127.0.0.1/tcp/4040/ipfs/{remoteId}";
            var          swarm         = new Swarm {
                LocalPeer = self
            };
            Peer unreachable = null;

            swarm.PeerNotReachable += (s, e) =>
            {
                unreachable = e;
            };
            swarm.StartAsync().Wait();
            try
            {
                ExceptionAssert.Throws <Exception>(() =>
                {
                    var _ = swarm.ConnectAsync(remoteAddress).Result;
                });
            }
            finally
            {
                swarm.StopAsync().Wait();
            }
            Assert.IsNotNull(unreachable);
            Assert.AreEqual(remoteId, unreachable.Id.ToBase58());
        }
예제 #6
0
        public async Task Connect_PrivateNetwork()
        {
            var peerB = new Peer
            {
                AgentVersion = "peerB",
                Id           = "QmdpwjdB94eNm2Lcvp9JqoCxswo3AKQqjLuNZyLixmCM1h",
                PublicKey    = "CAASXjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDlTSgVLprWaXfmxDr92DJE1FP0wOexhulPqXSTsNh5ot6j+UiuMgwb0shSPKzLx9AuTolCGhnwpTBYHVhFoBErAgMBAAE="
            };
            var swarmB = new Swarm {
                LocalPeer = peerB, NetworkProtector = new OpenNetwork()
            };
            await swarmB.StartAsync();

            var peerBAddress = await swarmB.StartListeningAsync("/ip4/127.0.0.1/tcp/0");

            Assert.IsTrue(peerB.Addresses.Count() > 0);

            var swarm = new Swarm {
                LocalPeer = self, NetworkProtector = new OpenNetwork()
            };
            await swarm.StartAsync();

            try
            {
                var remotePeer = await swarm.ConnectAsync(peerBAddress);

                Assert.AreEqual(2, OpenNetwork.Count);
            }
            finally
            {
                await swarm.StopAsync();

                await swarmB.StopAsync();
            }
        }
예제 #7
0
        public async Task RemotePeer_Contains_ConnectedAddress1()
        {
            var peerB = new Peer
            {
                AgentVersion = "peerB",
                Id           = "QmdpwjdB94eNm2Lcvp9JqoCxswo3AKQqjLuNZyLixmCM1h",
                PublicKey    = "CAASXjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDlTSgVLprWaXfmxDr92DJE1FP0wOexhulPqXSTsNh5ot6j+UiuMgwb0shSPKzLx9AuTolCGhnwpTBYHVhFoBErAgMBAAE="
            };
            var swarmB = new Swarm {
                LocalPeer = peerB
            };
            await swarmB.StartAsync();

            var peerBAddress = await swarmB.StartListeningAsync("/ip4/0.0.0.0/tcp/0");

            var swarm = new Swarm {
                LocalPeer = self
            };
            await swarm.StartAsync();

            try
            {
                var connection = await swarm.ConnectAsync(peerBAddress);

                var remote = connection.RemotePeer;
                Assert.AreEqual(remote.ConnectedAddress, peerBAddress);
                CollectionAssert.Contains(remote.Addresses.ToArray(), peerBAddress);
            }
            finally
            {
                await swarm.StopAsync();

                await swarmB.StopAsync();
            }
        }
예제 #8
0
        public void Connecting_To_Self()
        {
            var swarm = new Swarm {
                LocalPeer = self
            };

            ExceptionAssert.Throws <Exception>(() =>
            {
                swarm.ConnectAsync(earth).Wait();
            });
        }
예제 #9
0
        public void Connecting_To_Blacklisted_Address()
        {
            var swarm = new Swarm {
                LocalPeer = self
            };

            swarm.BlackList.Add(mars);
            ExceptionAssert.Throws <Exception>(() =>
            {
                swarm.ConnectAsync(mars).Wait();
            });
        }
예제 #10
0
        public async Task PermanentlyDead()
        {
            var peer = new Peer
            {
                Id        = "QmXFX2P5ammdmXQgfqGkfswtEVFsZUJ5KeHRXQYCTdiTAb",
                Addresses = new MultiAddress[]
                {
                    "/ip4/127.0.0.1/tcp/4040/ipfs/QmXFX2P5ammdmXQgfqGkfswtEVFsZUJ5KeHRXQYCTdiTAb"
                }
            };
            var swarm = new Swarm {
                LocalPeer = self
            };
            var manager = new PeerManager
            {
                Swarm          = swarm,
                InitialBackoff = TimeSpan.FromMilliseconds(100),
                MaxBackoff     = TimeSpan.FromMilliseconds(200),
            };

            Assert.AreEqual(0, manager.DeadPeers.Count);

            try
            {
                await swarm.StartAsync();

                await manager.StartAsync();

                try
                {
                    await swarm.ConnectAsync(peer);
                }
                catch { }
                Assert.AreEqual(1, manager.DeadPeers.Count);

                var end = DateTime.Now + TimeSpan.FromSeconds(6);
                while (DateTime.Now <= end)
                {
                    if (manager.DeadPeers[peer].NextAttempt == DateTime.MaxValue)
                    {
                        return;
                    }
                }
                Assert.Fail("not truely dead");
            }
            finally
            {
                await swarm.StopAsync();

                await manager.StopAsync();
            }
        }
예제 #11
0
        public void Connect_Not_Peer()
        {
            var          remoteId      = "QmXFX2P5ammdmXQgfqGkfswtEVFsZUJ5KeHRXQYCTdiTAb";
            MultiAddress remoteAddress = $"/dns/npmjs.com/tcp/80/ipfs/{remoteId}";
            var          swarm         = new Swarm {
                LocalPeer = self
            };

            ExceptionAssert.Throws <Exception>(() =>
            {
                var _ = swarm.ConnectAsync(remoteAddress).Result;
            });
        }
예제 #12
0
        public void Connect_Refused()
        {
            var          remoteId      = "QmXFX2P5ammdmXQgfqGkfswtEVFsZUJ5KeHRXQYCTdiTAb";
            MultiAddress remoteAddress = $"/ip4/127.0.0.1/tcp/4040/ipfs/{remoteId}";
            var          swarm         = new Swarm {
                LocalPeer = self
            };

            ExceptionAssert.Throws <Exception>(() =>
            {
                var _ = swarm.ConnectAsync(remoteAddress).Result;
            });
        }
예제 #13
0
        public async Task Backoff_Increases()
        {
            var peer = new Peer
            {
                Id        = "QmXFX2P5ammdmXQgfqGkfswtEVFsZUJ5KeHRXQYCTdiTxx",
                Addresses = new MultiAddress[]
                {
                    "/ip4/127.0.0.1/tcp/4040/ipfs/QmXFX2P5ammdmXQgfqGkfswtEVFsZUJ5KeHRXQYCTdiTxx"
                }
            };
            var swarm = new Swarm {
                LocalPeer = self
            };
            var manager = new PeerManager
            {
                Swarm          = swarm,
                InitialBackoff = TimeSpan.FromMilliseconds(100),
            };

            Assert.AreEqual(0, manager.DeadPeers.Count);

            try
            {
                await swarm.StartAsync();

                await manager.StartAsync();

                try
                {
                    await swarm.ConnectAsync(peer);
                }
                catch { }
                Assert.AreEqual(1, manager.DeadPeers.Count);

                var end = DateTime.Now + TimeSpan.FromSeconds(4);
                while (DateTime.Now <= end)
                {
                    if (manager.DeadPeers[peer].Backoff > manager.InitialBackoff)
                    {
                        return;
                    }
                }
                Assert.Fail("backoff did not increase");
            }
            finally
            {
                await swarm.StopAsync();

                await manager.StopAsync();
            }
        }
예제 #14
0
#pragma warning disable VSTHRD100 // Avoid async void methods
        /// <summary>
        ///   Called when the swarm has a new peer.
        /// </summary>
        /// <param name="sender">
        ///   The swarm of peers.
        /// </param>
        /// <param name="peer">
        ///   The peer that was discovered.
        /// </param>
        /// <remarks>
        ///   If the <see cref="MinConnections"/> is not reached, then the
        ///   <paramref name="peer"/> is dialed.
        /// </remarks>
        async void OnPeerDiscovered(object sender, Peer peer)
#pragma warning restore VSTHRD100 // Avoid async void methods
        {
            var n = swarm.Manager.Connections.Count() + pendingConnects;

            if (swarm.IsRunning && n < MinConnections)
            {
                Interlocked.Increment(ref pendingConnects);
                log.Debug($"Dialing new {peer}");
                try
                {
                    await swarm.ConnectAsync(peer).ConfigureAwait(false);
                }
                catch (Exception)
                {
                    log.Warn($"Failed to dial {peer}");
                }
                finally
                {
                    Interlocked.Decrement(ref pendingConnects);
                }
            }
        }
예제 #15
0
        public async Task Listening_IPv6Any()
        {
            var peerA = new Peer
            {
                Id           = self.Id,
                PublicKey    = self.PublicKey,
                AgentVersion = self.AgentVersion
            };
            MultiAddress addr   = "/ip6/::/tcp/0";
            var          swarmA = new Swarm {
                LocalPeer = peerA
            };
            var peerB = new Peer
            {
                Id           = other.Id,
                PublicKey    = other.PublicKey,
                AgentVersion = other.AgentVersion
            };
            var swarmB = new Swarm {
                LocalPeer = peerB
            };
            await swarmA.StartAsync();

            await swarmB.StartAsync();

            try
            {
                var another = await swarmA.StartListeningAsync(addr);

                Assert.IsFalse(peerA.Addresses.Contains(addr));
                Assert.IsTrue(peerA.Addresses.Contains(another));

                await swarmB.ConnectAsync(another);

                Assert.IsTrue(swarmB.KnownPeers.Contains(peerA));
                // TODO: Assert.IsTrue(swarmA.KnownPeers.Contains(peerB));

                await swarmA.StopListeningAsync(addr);

                Assert.AreEqual(0, peerA.Addresses.Count());
            }
            finally
            {
                await swarmA.StopAsync();

                await swarmB.StopAsync();
            }
        }
예제 #16
0
        public void Connect_Cancelled()
        {
            var cs = new CancellationTokenSource();

            cs.Cancel();
            var          remoteId      = "QmXFX2P5ammdmXQgfqGkfswtEVFsZUJ5KeHRXQYCTdiTAb";
            MultiAddress remoteAddress = $"/ip4/127.0.0.1/tcp/4002/ipfs/{remoteId}";
            var          swarm         = new Swarm {
                LocalPeer = self
            };

            ExceptionAssert.Throws <Exception>(() =>
            {
                var _ = swarm.ConnectAsync(remoteAddress, cs.Token).Result;
            });
        }
예제 #17
0
        public async Task PeerDisconnected()
        {
            var peerB = new Peer
            {
                AgentVersion = "peerB",
                Id           = "QmdpwjdB94eNm2Lcvp9JqoCxswo3AKQqjLuNZyLixmCM1h",
                PublicKey    = "CAASXjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDlTSgVLprWaXfmxDr92DJE1FP0wOexhulPqXSTsNh5ot6j+UiuMgwb0shSPKzLx9AuTolCGhnwpTBYHVhFoBErAgMBAAE="
            };
            var swarmB = new Swarm {
                LocalPeer = peerB
            };
            await swarmB.StartAsync();

            var peerBAddress = await swarmB.StartListeningAsync("/ip4/127.0.0.1/tcp/0");

            var swarm = new Swarm {
                LocalPeer = self
            };
            var swarmConnections = 0;

            swarm.ConnectionEstablished += (s, e) =>
            {
                ++swarmConnections;
            };
            swarm.PeerDisconnected += (s, e) =>
            {
                --swarmConnections;
            };
            await swarm.StartAsync();

            try
            {
                var remotePeer = await swarm.ConnectAsync(peerBAddress);

                Assert.AreEqual(1, swarmConnections);

                await swarm.StopAsync();

                Assert.AreEqual(0, swarmConnections);
            }
            finally
            {
                await swarm.StopAsync();

                await swarmB.StopAsync();
            }
        }
예제 #18
0
        public async Task RemotePeer_Contains_ConnectedAddress2()
        {
            // Only works on Windows because connecting to 127.0.0.100 is allowed
            // when listening on 0.0.0.0
            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                return;
            }

            var peerB = new Peer
            {
                AgentVersion = "peerB",
                Id           = "QmdpwjdB94eNm2Lcvp9JqoCxswo3AKQqjLuNZyLixmCM1h",
                PublicKey    = "CAASXjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDlTSgVLprWaXfmxDr92DJE1FP0wOexhulPqXSTsNh5ot6j+UiuMgwb0shSPKzLx9AuTolCGhnwpTBYHVhFoBErAgMBAAE="
            };
            var swarmB = new Swarm {
                LocalPeer = peerB
            };
            await swarmB.StartAsync();

            var peerBAddress = await swarmB.StartListeningAsync("/ip4/0.0.0.0/tcp/0");

            var peerBPort = peerBAddress.Protocols[1].Value;

            Assert.IsTrue(peerB.Addresses.Count() > 0);

            var swarm = new Swarm {
                LocalPeer = self
            };
            await swarm.StartAsync();

            try
            {
                MultiAddress ma         = $"/ip4/127.0.0.100/tcp/{peerBPort}/ipfs/{peerB.Id}";
                var          connection = await swarm.ConnectAsync(ma);

                var remote = connection.RemotePeer;
                Assert.AreEqual(remote.ConnectedAddress, ma);
                CollectionAssert.Contains(remote.Addresses.ToArray(), ma);
            }
            finally
            {
                await swarm.StopAsync();

                await swarmB.StopAsync();
            }
        }
예제 #19
0
        public async Task Connect_WithSomeUnreachableAddresses()
        {
            var bid   = "QmdpwjdB94eNm2Lcvp9JqoCxswo3AKQqjLuNZyLixmCM1h";
            var peerB = new Peer
            {
                AgentVersion = "peerB",
                Id           = bid,
                PublicKey    = "CAASXjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDlTSgVLprWaXfmxDr92DJE1FP0wOexhulPqXSTsNh5ot6j+UiuMgwb0shSPKzLx9AuTolCGhnwpTBYHVhFoBErAgMBAAE=",
                Addresses    = new MultiAddress[]
                {
                    $"/ip4/127.0.0.2/tcp/2/ipfs/{bid}",
                    $"/ip4/127.0.0.3/tcp/3/ipfs/{bid}"
                }
            };
            var swarmB = new Swarm {
                LocalPeer = peerB
            };
            await swarmB.StartAsync();

            var peerBAddress = await swarmB.StartListeningAsync("/ip4/127.0.0.1/tcp/0");

            Assert.IsTrue(peerB.Addresses.Count() > 0);

            var swarm = new Swarm {
                LocalPeer = self
            };
            await swarm.StartAsync();

            try
            {
                var remotePeer = await swarm.ConnectAsync(peerB);

                Assert.IsNotNull(remotePeer.ConnectedAddress);
                Assert.AreEqual(peerB.PublicKey, remotePeer.PublicKey);
                Assert.IsTrue(remotePeer.IsValid());
                Assert.IsTrue(swarm.KnownPeers.Contains(peerB));
            }
            finally
            {
                await swarm.StopAsync();

                await swarmB.StopAsync();
            }
        }
예제 #20
0
        public void Connecting_To_Self()
        {
            var swarm = new Swarm {
                LocalPeer = self
            };

            swarm.StartAsync().Wait();
            try
            {
                ExceptionAssert.Throws <Exception>(() =>
                {
                    var _ = swarm.ConnectAsync(earth).Result;
                });
            }
            finally
            {
                swarm.StopAsync().Wait();
            }
        }
예제 #21
0
        public void Connecting_To_Blacklisted_Address()
        {
            var swarm = new Swarm {
                LocalPeer = self
            };

            swarm.BlackList.Add(mars);
            swarm.StartAsync().Wait();
            try
            {
                ExceptionAssert.Throws <Exception>(() =>
                {
                    var _ = swarm.ConnectAsync(mars).Result;
                });
            }
            finally
            {
                swarm.StopAsync().Wait();
            }
        }
예제 #22
0
        public void Connect_No_Transport()
        {
            var          remoteId      = "QmXFX2P5ammdmXQgfqGkfswtEVFsZUJ5KeHRXQYCTdiTAb";
            MultiAddress remoteAddress = $"/ip4/127.0.0.1/ipfs/{remoteId}";
            var          swarm         = new Swarm {
                LocalPeer = self
            };

            swarm.StartAsync().Wait();
            try
            {
                ExceptionAssert.Throws <Exception>(() =>
                {
                    var _ = swarm.ConnectAsync(remoteAddress).Result;
                });
            }
            finally
            {
                swarm.StopAsync().Wait();
            }
        }
예제 #23
0
        public async Task Connecting_To_Self_Indirect()
        {
            var swarm = new Swarm {
                LocalPeer = self
            };
            await swarm.StartAsync();

            try
            {
                var listen = await swarm.StartListeningAsync("/ip4/127.0.0.1/tcp/0");

                var bad = listen.Clone();
                bad.Protocols[2].Value = "QmXFX2P5ammdmXQgfqGkfswtEVFsZUJ5KeHRXQYCTdiTAb";
                ExceptionAssert.Throws <Exception>(() =>
                {
                    swarm.ConnectAsync(bad).Wait();
                });
            }
            finally
            {
                await swarm.StopAsync();
            }
        }
예제 #24
0
        public async Task Connect_Disconnect_Reconnect()
        {
            var peerB = new Peer
            {
                AgentVersion = "peerB",
                Id           = "QmdpwjdB94eNm2Lcvp9JqoCxswo3AKQqjLuNZyLixmCM1h",
                PublicKey    = "CAASXjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDlTSgVLprWaXfmxDr92DJE1FP0wOexhulPqXSTsNh5ot6j+UiuMgwb0shSPKzLx9AuTolCGhnwpTBYHVhFoBErAgMBAAE="
            };
            var swarmB = new Swarm {
                LocalPeer = peerB
            };
            await swarmB.StartAsync();

            var peerBAddress = await swarmB.StartListeningAsync("/ip4/127.0.0.1/tcp/0");

            Assert.IsTrue(peerB.Addresses.Count() > 0);

            var swarm = new Swarm {
                LocalPeer = self
            };
            await swarm.StartAsync();

            await swarm.StartListeningAsync("/ip4/127.0.0.1/tcp/0");

            try
            {
                var remotePeer = (await swarm.ConnectAsync(peerBAddress)).RemotePeer;
                Assert.IsNotNull(remotePeer.ConnectedAddress);
                Assert.AreEqual(peerB.PublicKey, remotePeer.PublicKey);
                Assert.IsTrue(remotePeer.IsValid());
                Assert.IsTrue(swarm.KnownPeers.Contains(peerB));

                // wait for swarmB to settle
                var endTime = DateTime.Now.AddSeconds(3);
                while (true)
                {
                    if (DateTime.Now > endTime)
                    {
                        Assert.Fail("swarmB does not know about self");
                    }
                    if (swarmB.KnownPeers.Contains(self))
                    {
                        break;
                    }
                    await Task.Delay(100);
                }
                var me = swarmB.KnownPeers.First(p => p == self);
                Assert.AreEqual(self.Id, me.Id);
                Assert.AreEqual(self.PublicKey, me.PublicKey);
                Assert.IsNotNull(me.ConnectedAddress);

                // Check disconnect
                await swarm.DisconnectAsync(peerBAddress);

                Assert.IsNull(remotePeer.ConnectedAddress);
                Assert.IsTrue(swarm.KnownPeers.Contains(peerB));
                Assert.IsTrue(swarmB.KnownPeers.Contains(self));

                // wait for swarmB to settle
                endTime = DateTime.Now.AddSeconds(3);
                while (true)
                {
                    if (DateTime.Now > endTime)
                    {
                        Assert.Fail("swarmB did not close connection.");
                    }
                    if (me.ConnectedAddress == null)
                    {
                        break;
                    }
                    await Task.Delay(100);
                }

                // Reconnect
                remotePeer = (await swarm.ConnectAsync(peerBAddress)).RemotePeer;
                Assert.IsNotNull(remotePeer.ConnectedAddress);
                Assert.AreEqual(peerB.PublicKey, remotePeer.PublicKey);
                Assert.IsTrue(remotePeer.IsValid());
                Assert.IsTrue(swarm.KnownPeers.Contains(peerB));
            }
            finally
            {
                await swarm.StopAsync();

                await swarmB.StopAsync();
            }
        }