Example #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);
        }
Example #2
0
        void TaskComplete(object sender, TaskCompleteEventArgs e)
        {
            e.Task.Completed -= TaskComplete;

            // I should raise the event with some eventargs saying which node was dead
            SendQueryEventArgs args = (SendQueryEventArgs)e;

            if (args.TimedOut)
            {
                // If the node didn't respond and it's no longer in our bucket,
                // we need to send a ping to the oldest node in the bucket
                // Otherwise if we have a non-responder and it's still there, replace it!
                int index = bucket.Nodes.IndexOf(((SendQueryTask)e.Task).Target);
                if (index < 0)
                {
                    SendPingToOldest();
                }
                else
                {
                    bucket.Nodes[index] = newNode;
                    RaiseComplete(new TaskCompleteEventArgs(this));
                }
            }
            else
            {
                SendPingToOldest();
            }
        }
Example #3
0
        private static void FindNodeComplete(object sender, TaskCompleteEventArgs e)
        {
            SendQueryEventArgs args = (SendQueryEventArgs)e;

            lock (engine)
                activities--;
            if (!args.TimedOut)
            {
                logAdd("Visited");
                if (find_queue.Count < 10000)
                {
                    FindNodeResponse response = (FindNodeResponse)args.Response;
                    var ns = Node.FromCompactNode(response.Nodes);
                    foreach (var n in ns)
                    {
                        //Console.WriteLine("Find {1} Node: {0}", n.Id, nodes.Count);
                        lock (find_queue)
                            find_queue.Enqueue(n);
                    }
                }
            }
            else
            {
                nodes.RemoveWhere(n => ((FindNode)args.Query).Target == n.Id);
            }
        }
        private void MessageSent(object sender, SendQueryEventArgs e)
        {
            if (e.Query != query)
            {
                return;
            }

            // If the message timed out and we we haven't already hit the maximum retries
            // send again. Otherwise we propagate the eventargs through the Complete event.
            if (e.TimedOut)
            {
                node.FailedCount++;
            }
            else
            {
                Target.LastSeen = DateTime.UtcNow;
            }

            if (e.TimedOut && --retries > 0)
            {
                engine.MessageLoop.EnqueueSend(query, node);
            }
            else
            {
                RaiseComplete(e);
            }
        }
Example #5
0
        private void GetPeersCompleted(object o, TaskCompleteEventArgs e)
        {
            try
            {
                activeQueries--;
                e.Task.Completed -= GetPeersCompleted;

                SendQueryEventArgs args = (SendQueryEventArgs)e;

                // We want to keep a list of the top (K) closest nodes which have responded
                Node target = ((SendQueryTask)args.Task).Target;
                int  index  = queriedNodes.Values.IndexOf(target);
                if (index >= Bucket.MaxCapacity || args.TimedOut)
                {
                    queriedNodes.RemoveAt(index);
                }

                if (args.TimedOut)
                {
                    return;
                }

                GetPeersResponse response = (GetPeersResponse)args.Response;

                // Ensure that the local Node object has the token. There may/may not be
                // an additional copy in the routing table depending on whether or not
                // it was able to fit into the table.
                target.Token = response.Token;
                if (response.Values != null)
                {
                    // We have actual peers!
                    engine.RaisePeersFound(infoHash, MonoTorrent.Client.Peer.Decode(response.Values));
                }
                else if (response.Nodes != null)
                {
                    if (!Active)
                    {
                        return;
                    }

                    // We got a list of nodes which are closer
                    IEnumerable <Node> newNodes = Node.FromCompactNode(response.Nodes);
                    foreach (Node n in Node.CloserNodes(infoHash, closestNodes, newNodes, Bucket.MaxCapacity))
                    {
                        SendGetPeers(n);
                    }
                }
            }
            finally
            {
                if (activeQueries == 0)
                {
                    RaiseComplete(new TaskCompleteEventArgs(this));
                }
            }
        }
        private void FindNodeComplete(object sender, TaskCompleteEventArgs e)
        {
            e.Task.Completed -= FindNodeComplete;
            activeRequests--;

            SendQueryEventArgs args = (SendQueryEventArgs)e;

            if (!args.TimedOut)
            {
                FindNodeResponse response = (FindNodeResponse)args.Response;
                SendFindNode(Node.FromCompactNode(response.Nodes));
            }

            if (activeRequests == 0)
            {
                RaiseComplete(new TaskCompleteEventArgs(this));
            }
        }
Example #7
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();
            }
        }
Example #8
0
        public async System.Threading.Tasks.Task Execute()
        {
            if (bucket.Nodes.Count == 0)
            {
                return;
            }

            bucket.Changed();
            bucket.SortBySeen();

            if (bucket.Nodes[0].LastSeen < TimeSpan.FromMinutes(3))
            {
                return;
            }
            else
            {
                Node oldest             = bucket.Nodes[0];
                SendQueryEventArgs args = await engine.SendQueryAsync(new Ping (engine.LocalId), oldest);

                if (args.TimedOut)
                {
                    // If the node didn't respond and it's no longer in our bucket,
                    // we need to send a ping to the oldest node in the bucket
                    // Otherwise if we have a non-responder and it's still there, replace it!
                    int index = bucket.Nodes.IndexOf(oldest);
                    if (index < 0)
                    {
                        await Execute();
                    }
                    else
                    {
                        bucket.Nodes[index] = newNode;
                        return;
                    }
                }
                else
                {
                    await Execute();
                }
            }
        }
Example #9
0
        private void MessageSent(object sender, SendQueryEventArgs e)
        {
            if (e.Query != query)
                return;

            // If the message timed out and we we haven't already hit the maximum retries
            // send again. Otherwise we propagate the eventargs through the Complete event.
            if (e.TimedOut)
                node.FailedCount++;
            else
                Target.LastSeen = DateTime.UtcNow;

            if (e.TimedOut && --retries > 0)
            {
                engine.MessageLoop.EnqueueSend(query, node);
            }
            else
            {
                RaiseComplete(e);
            }
        }
Example #10
0
        public async Task Execute()
        {
            if (bucket.Nodes.Count == 0)
            {
                return;
            }

            bucket.SortBySeen();

            foreach (Node node in bucket.Nodes.ToArray())
            {
                var message = new FindNode(engine.LocalId, node.Id);

                SendQueryEventArgs args = await engine.SendQueryAsync(message, node);

                if (!args.TimedOut)
                {
                    return;
                }
            }
        }
Example #11
0
        private void TaskComplete(object o, TaskCompleteEventArgs e)
        {
            _task.Completed -= TaskComplete;

            SendQueryEventArgs args = (SendQueryEventArgs)e;

            if (args.TimedOut)
            {
                _bucket.SortBySeen();
                int index = _bucket.Nodes.IndexOf(_node);
                if ((index == -1) || (++index < _bucket.Nodes.Count))
                {
                    QueryNode(_bucket.Nodes[0]);
                }
                else
                {
                    RaiseComplete(new TaskCompleteEventArgs(this));
                }
            }
            else
            {
                RaiseComplete(new TaskCompleteEventArgs(this));
            }
        }