Exemple #1
0
        public async Task <IEnumerable <Node> > ExecuteAsync()
        {
            var activeQueries      = new List <Task <SendQueryEventArgs> > ();
            var closestNodes       = new ClosestNodesCollection(InfoHash);
            var closestActiveNodes = new ClosestNodesCollection(InfoHash);

            foreach (Node node in Engine.RoutingTable.GetClosest(InfoHash))
            {
                if (closestNodes.Add(node))
                {
                    activeQueries.Add(Engine.SendQueryAsync(new GetPeers(Engine.LocalId, InfoHash), node));
                }
            }

            while (activeQueries.Count > 0)
            {
                var completed = await Task.WhenAny(activeQueries);

                activeQueries.Remove(completed);

                // If it timed out or failed just move to the next query.
                SendQueryEventArgs query = await completed;
                if (query.Response == null)
                {
                    continue;
                }

                var response = (GetPeersResponse)query.Response;
                // The response had some actual peers
                if (response.Values != null)
                {
                    // We have actual peers!
                    var peers = Peer.Decode(response.Values);
                    Engine.RaisePeersFound(InfoHash, peers);
                    foreach (var peer in peers)
                    {
                        FoundPeers.Add(peer);
                    }
                }

                // The response contains nodes which should be closer to our target. If they are closer than nodes
                // we've already checked, then let's query them!
                if (response.Nodes != null && FoundPeers.Count < MaxPeers)
                {
                    foreach (Node node in Node.FromCompactNode(response.Nodes))
                    {
                        if (closestNodes.Add(node))
                        {
                            activeQueries.Add(Engine.SendQueryAsync(new GetPeers(Engine.LocalId, InfoHash), node));
                        }
                    }
                }

                closestActiveNodes.Add(query.Node);
            }

            // Finally, return the 8 closest nodes we discovered during this phase. These are the nodes we should
            // announce to later.
            return(closestActiveNodes);
        }
Exemple #2
0
        async Task SendFindNode(IEnumerable <Node> newNodes)
        {
            var activeRequests = new List <Task <SendQueryEventArgs> > ();
            var nodes          = new ClosestNodesCollection(engine.LocalId);

            foreach (Node node in newNodes)
            {
                var request = new FindNode(engine.LocalId, engine.LocalId);
                activeRequests.Add(engine.SendQueryAsync(request, node));
                nodes.Add(node);
            }

            while (activeRequests.Count > 0)
            {
                var completed = await Task.WhenAny(activeRequests);

                activeRequests.Remove(completed);

                SendQueryEventArgs args = await completed;
                if (args.Response != null)
                {
                    if (engine.RoutingTable.CountNodes() >= MinHealthyNodes)
                    {
                        initializationComplete.TrySetResult(null);
                    }

                    var response = (FindNodeResponse)args.Response;
                    foreach (Node node in Node.FromCompactNode(response.Nodes))
                    {
                        if (nodes.Add(node))
                        {
                            var request = new FindNode(engine.LocalId, engine.LocalId);
                            activeRequests.Add(engine.SendQueryAsync(request, node));
                        }
                    }
                }
            }

            if (initialNodes.Count > 0 && engine.RoutingTable.NeedsBootstrap)
            {
                await new InitialiseTask(engine).ExecuteAsync();
            }
        }