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; }
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 }
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); }
int CountPeerRequired(int peerToFind) { return(Math.Max(0, peerToFind - PeerTable.CountUsed(true))); }
/// <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"); } }
private void AssertPeer(PeerTable table, string peer, Action<Peer> test) { test(table.GetPeer(new IPEndPoint(IPAddress.Parse(peer), 100))); }