コード例 #1
0
ファイル: PeerTableTests.cs プロジェクト: nikropht/NBitcoin
 private Peer AddPeer(PeerTable table, string addr, PeerOrigin peerOrigin, DateTimeOffset now)
 {
     var peer = new Peer(peerOrigin, new NetworkAddress()
     {
         Endpoint = new IPEndPoint(IPAddress.Parse(addr), 100),
         Time = now
     });
     table.WritePeer(peer);
     return peer;
 }
コード例 #2
0
ファイル: PeerTableTests.cs プロジェクト: nikropht/NBitcoin
        public void CanStorePeers()
        {
            PeerTable table = new PeerTable();
            table.Randomize = false;
            AssertPeer(table, "1.0.0.0", p => Assert.Null(p));
            AddPeer(table, "1.0.0.0", PeerOrigin.Addr, DateTimeOffset.Now);
            AssertPeer(table, "1.0.0.0", p => Assert.NotNull(p));
            Assert.True(table.GetActivePeers(10).Length == 1);

            AssertPeer(table, "1.0.0.1", p => Assert.Null(p));
            AddPeer(table, "1.0.0.1", PeerOrigin.Addr, DateTimeOffset.Now - TimeSpan.FromHours(4.0));
            AssertPeer(table, "1.0.0.1", p => Assert.Null(p));

            //Second peer should be expired
            Assert.True(table.GetActivePeers(10).Length == 1);

            AddPeer(table, "1.0.0.1", PeerOrigin.Addr, DateTimeOffset.Now - TimeSpan.FromHours(2.0));
            Assert.True(table.GetActivePeers(10).Length == 2);

            Assert.True(table.GetActivePeers(1).Length == 1);

            AddPeer(table, "1.0.0.2", PeerOrigin.DNSSeed, DateTimeOffset.Now);

            var peers = table.GetActivePeers(10);
            Assert.Equal(CreateEndpoint("1.0.0.0"), peers[0].NetworkAddress.Endpoint); //Most recent
            Assert.Equal(CreateEndpoint("1.0.0.1"), peers[1].NetworkAddress.Endpoint);
            Assert.Equal(CreateEndpoint("1.0.0.2"), peers[2].NetworkAddress.Endpoint); //Seeds
            Assert.Equal(2, table.CountUsed());

            //Can add two time a seed
            AddPeer(table, "1.0.0.2", PeerOrigin.DNSSeed, DateTimeOffset.Now);

            AddPeer(table, "1.0.0.1", PeerOrigin.Addr, DateTimeOffset.Now - TimeSpan.FromHours(4.0));

            peers = table.GetActivePeers(10);
            Assert.Equal(CreateEndpoint("1.0.0.0"), peers[0].NetworkAddress.Endpoint); //Most recent
            //Assert.Equal(CreateEndpoint("1.0.0.1"), peers[1].NetworkAddress.Endpoint); Expired
            Assert.Equal(CreateEndpoint("1.0.0.2"), peers[1].NetworkAddress.Endpoint); //Seeds

            Assert.Equal(1, table.CountUsed()); //Seed does not count
            Assert.Equal(2, table.CountUsed(false)); //Seed count

            var p1 = AddPeer(table, "1.0.0.4", PeerOrigin.DNSSeed, DateTimeOffset.Now - TimeSpan.FromHours(4.0));

            Assert.Equal(3, table.CountUsed(false)); //Expired seeds should still appear
            table.RemovePeer(p1);
            Assert.Equal(2, table.CountUsed(false)); //Removed
        }
コード例 #3
0
        public NodeSet CreateNodeSet(int size)
        {
            if (size > 1000)
            {
                throw new ArgumentOutOfRangeException("size", "size should be less than 1000");
            }
            TraceCorrelation trace = new TraceCorrelation(NodeServerTrace.Trace, "Creating node set of size " + size);
            NodeSet          set   = new NodeSet();

            using (trace.Open())
            {
                while (set.Count() < size)
                {
                    var peerToGet   = size - set.Count();
                    var activePeers = PeerTable.GetActivePeers(1000);
                    activePeers = activePeers.Where(p => !set.Contains(p.NetworkAddress.Endpoint)).ToArray();
                    if (activePeers.Length < peerToGet)
                    {
                        DiscoverPeers(size);
                        continue;
                    }
                    NodeServerTrace.Information("Need " + peerToGet + " more nodes");

                    BlockingCollection <Node> handshakedNodes = new BlockingCollection <Node>(peerToGet);
                    CancellationTokenSource   handshakedFull  = new CancellationTokenSource();

                    try
                    {
                        Parallel.ForEach(activePeers,
                                         new ParallelOptions()
                        {
                            MaxDegreeOfParallelism = 10,
                            CancellationToken      = handshakedFull.Token
                        }, p =>
                        {
                            if (set.Contains(p.NetworkAddress.Endpoint))
                            {
                                return;
                            }
                            Node node = null;
                            try
                            {
                                node = GetNodeByPeer(p, handshakedFull.Token);
                                node.VersionHandshake(handshakedFull.Token);
                                if (node != null && node.State != NodeState.HandShaked)
                                {
                                    node.Disconnect();
                                }
                                if (!handshakedNodes.TryAdd(node))
                                {
                                    handshakedFull.Cancel();
                                    node.Disconnect();
                                }
                                else
                                {
                                    var remaining = (size - set.Count() - handshakedNodes.Count);
                                    if (remaining == 0)
                                    {
                                        handshakedFull.Cancel();
                                    }
                                    else
                                    {
                                        NodeServerTrace.Information("Need " + remaining + " more nodes");
                                    }
                                }
                            }
                            catch (Exception)
                            {
                                if (node != null)
                                {
                                    node.Disconnect();
                                }
                            }
                        });
                    }
                    catch (OperationCanceledException)
                    {
                    }
                    set.AddNodes(handshakedNodes.ToArray());
                }
            }
            return(set);
        }
コード例 #4
0
 int CountPeerRequired(int peerToFind)
 {
     return(Math.Max(0, peerToFind - PeerTable.CountUsed(true)));
 }
コード例 #5
0
        /// <summary>
        /// Fill the PeerTable with fresh addresses
        /// </summary>
        public void DiscoverPeers(int peerToFind = 990)
        {
            TraceCorrelation traceCorrelation = new TraceCorrelation(NodeServerTrace.Trace, "Discovering nodes");
            List <Task>      tasks            = new List <Task>();

            using (traceCorrelation.Open())
            {
                while (CountPeerRequired(peerToFind) != 0)
                {
                    NodeServerTrace.PeerTableRemainingPeerToGet(CountPeerRequired(peerToFind));
                    var peers = PeerTable.GetActivePeers(1000);
                    if (peers.Length == 0)
                    {
                        PopulateTableWithDNSNodes();
                        PopulateTableWithHardNodes();
                        peers = PeerTable.GetActivePeers(1000);
                    }


                    CancellationTokenSource peerTableFull = new CancellationTokenSource();
                    NodeSet connected = new NodeSet();
                    try
                    {
                        Parallel.ForEach(peers, new ParallelOptions()
                        {
                            MaxDegreeOfParallelism = 5,
                            CancellationToken      = peerTableFull.Token,
                        }, p =>
                        {
                            CancellationTokenSource cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(40));
                            Node n = null;
                            try
                            {
                                n = GetNodeByPeer(p, cancellation.Token);
                                if (n.State < NodeState.HandShaked)
                                {
                                    connected.AddNode(n);
                                    n.VersionHandshake(cancellation.Token);
                                }
                                n.SendMessage(new GetAddrPayload());
                                Thread.Sleep(2000);
                            }
                            catch (Exception)
                            {
                                if (n != null)
                                {
                                    n.Disconnect();
                                }
                            }
                            if (CountPeerRequired(peerToFind) == 0)
                            {
                                peerTableFull.Cancel();
                            }
                            else
                            {
                                NodeServerTrace.Information("Need " + CountPeerRequired(peerToFind) + " more peers");
                            }
                        });
                    }
                    catch (OperationCanceledException)
                    {
                    }
                    finally
                    {
                        connected.DisconnectAll();
                    }
                }
                NodeServerTrace.Trace.TraceInformation("Peer table is now full");
            }
        }
コード例 #6
0
ファイル: PeerTableTests.cs プロジェクト: nikropht/NBitcoin
 private void AssertPeer(PeerTable table, string peer, Action<Peer> test)
 {
     test(table.GetPeer(new IPEndPoint(IPAddress.Parse(peer), 100)));
 }