示例#1
0
        protected virtual async void HandlePeerExchangeMessage(PeerId id, PeerExchangeMessage message)
        {
            // Ignore peer exchange messages on private toirrents
            if ((Manager.Torrent != null && Manager.Torrent.IsPrivate) || !Manager.Settings.AllowPeerExchange)
            {
                Manager.RaisePeersFound(new PeerExchangePeersAdded(Manager, 0, 0, id));
            }
            else
            {
                // If we already have lots of peers, don't process the messages anymore.
                if ((Manager.Peers.Available + Manager.OpenConnections) >= Manager.Settings.MaximumConnections)
                {
                    return;
                }

                IList <Peer> newPeers = Peer.Decode(message.Added);
                for (int i = 0; i < newPeers.Count && i < message.AddedDotF.Length; i++)
                {
                    newPeers[i].IsSeeder = (message.AddedDotF[i] & 0x2) == 0x2;
                }
                int count = await Manager.AddPeersAsync(newPeers);

                Manager.RaisePeersFound(new PeerExchangePeersAdded(Manager, count, newPeers.Count, id));
            }
        }
示例#2
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);
        }
示例#3
0
 public void DecodeCompact()
 {
     byte[] bytes = new byte[_peers.Count * 6];
     for (int i = 0; i < _peers.Count; i++)
     {
         _peers[i].CompactPeer(bytes, i * 6);
     }
     VerifyDecodedPeers(Peer.Decode((BEncodedString)bytes));
 }
示例#4
0
        private async Task SendGetPeers(Node target)
        {
            NodeId distance = target.Id.Xor(infoHash);

            ClosestActiveNodes.Add(distance, target);

            GetPeers m = new GetPeers(engine.LocalId, infoHash);

            activeQueries++;
            var args = await engine.SendQueryAsync(m, target);

            activeQueries--;

            // We want to keep a list of the top (K) closest nodes which have responded
            int index = ClosestActiveNodes.Values.IndexOf(target);

            if (index >= Bucket.MaxCapacity || args.TimedOut)
            {
                ClosestActiveNodes.RemoveAt(index);
            }

            if (args.TimedOut)
            {
                if (activeQueries == 0)
                {
                    tcs.TrySetResult(new Node[0]);
                }
                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, Peer.Decode(response.Values));
            }
            else if (response.Nodes != null)
            {
                // We got a list of nodes which are closer
                IEnumerable <Node> newNodes = Node.FromCompactNode(response.Nodes);
                foreach (Node closer in Node.CloserNodes(infoHash, ClosestNodes, newNodes, Bucket.MaxCapacity))
                {
                    await SendGetPeers(closer);
                }
            }

            if (activeQueries == 0)
            {
                tcs.TrySetResult(ClosestActiveNodes.Values.ToArray());
            }
        }
示例#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  = ClosestActiveNodes.Values.IndexOf(target);
                if ((index >= Config.MaxBucketCapacity) || args.TimedOut)
                {
                    ClosestActiveNodes.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, 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, Config.MaxBucketCapacity))
                    {
                        SendGetPeers(n);
                    }
                }
            }
            finally
            {
                if (_activeQueries == 0)
                {
                    RaiseComplete(new TaskCompleteEventArgs(this));
                }
            }
        }
示例#6
0
        private void HandleAnnounce(BEncodedDictionary dict, List <Peer> peers)
        {
            foreach (var keypair in dict)
            {
                switch (keypair.Key.Text)
                {
                case ("complete"):
                    Complete = Convert.ToInt32(keypair.Value.ToString());
                    break;

                case ("incomplete"):
                    Incomplete = Convert.ToInt32(keypair.Value.ToString());
                    break;

                case ("downloaded"):
                    Downloaded = Convert.ToInt32(keypair.Value.ToString());
                    break;

                case ("tracker id"):
                    _trackerId = keypair.Value.ToString();
                    break;

                case ("min interval"):
                    MinUpdateInterval = TimeSpan.FromSeconds(int.Parse(keypair.Value.ToString()));
                    break;

                case ("interval"):
                    UpdateInterval = TimeSpan.FromSeconds(int.Parse(keypair.Value.ToString()));
                    break;

                case ("peers"):
                    if (keypair.Value is BEncodedList)     // Non-compact response
                    {
                        peers.AddRange(Peer.Decode((BEncodedList)keypair.Value));
                    }
                    else if (keypair.Value is BEncodedString)     // Compact response
                    {
                        peers.AddRange(Peer.Decode((BEncodedString)keypair.Value));
                    }
                    break;

                case ("failure reason"):
                    FailureMessage = keypair.Value.ToString();
                    break;

                case ("warning message"):
                    WarningMessage = keypair.Value.ToString();
                    break;

                default:
                    Debug.WriteLine("HttpTracker - Unknown announce tag received: Key {0}  Value: {1}",
                                    keypair.Key, keypair.Value);
                    break;
                }
            }
        }
示例#7
0
        public void CorruptDictionary()
        {
            var list       = new BEncodedList();
            var dictionary = new BEncodedDictionary();

            list.Add(dictionary);
            IList <Peer> decoded = Peer.Decode(list);

            Assert.AreEqual(0, decoded.Count, "#1");
        }
示例#8
0
        public void CompactPeerTest()
        {
            const string peerId = "12345abcde12345abcde";

            var uri     = new Uri("tcp://192.168.0.5:12345");
            var p       = new Peer(peerId, uri);
            var compact = p.CompactPeer();
            var peer    = Peer.Decode(compact)[0];

            Assert.AreEqual(p.ConnectionUri, peer.ConnectionUri);
        }
示例#9
0
        public void DecodeList()
        {
            // List of String
            BEncodedList list = new BEncodedList();

            foreach (Peer p in _peers)
            {
                list.Add((BEncodedString)p.CompactPeer());
            }

            VerifyDecodedPeers(Peer.Decode(list));
        }
示例#10
0
        public void CorruptString()
        {
            IList <Peer> p = Peer.Decode((BEncodedString)"1234");

            Assert.AreEqual(0, p.Count, "#1");

            byte[] b = new byte[] { 255, 255, 255, 255, 255, 255 };
            p = Peer.Decode((BEncodedString)b);
            Assert.AreEqual(1, p.Count, "#2");

            b = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            p = Peer.Decode((BEncodedString)b);
            Assert.AreEqual(1, p.Count, "#3");
        }
示例#11
0
        public void DecodeDictionary()
        {
            BEncodedList list = new BEncodedList();

            foreach (Peer p in _peers)
            {
                BEncodedDictionary dict = new BEncodedDictionary();
                dict.Add("ip", (BEncodedString)p.ConnectionUri.Host);
                dict.Add("port", (BEncodedNumber)p.ConnectionUri.Port);
                dict.Add("peer id", (BEncodedString)p.PeerId);
                list.Add(dict);
            }

            VerifyDecodedPeers(Peer.Decode(list));
        }
示例#12
0
        public void CorruptList()
        {
            BEncodedList list = new BEncodedList();

            for (int i = 0; i < _peers.Count; i++)
            {
                list.Add((BEncodedString)_peers[i].CompactPeer());
            }

            list.Insert(2, new BEncodedNumber(5));
            VerifyDecodedPeers(Peer.Decode(list));

            list.Clear();
            list.Add(new BEncodedString(new byte[3]));
            IList <Peer> decoded = Peer.Decode(list);

            Assert.AreEqual(0, decoded.Count, "#1");
        }
示例#13
0
        protected virtual void HandlePeerExchangeMessage(PeerId id, PeerExchangeMessage message)
        {
            // Ignore peer exchange messages on private torrents
            if (id.TorrentManager.Torrent.IsPrivate || !id.TorrentManager.Settings.EnablePeerExchange)
            {
                return;
            }

            // If we already have lots of peers, don't process the messages anymore.
            if ((Manager.Peers.Available + Manager.OpenConnections) >= Manager.Settings.MaxConnections)
            {
                return;
            }

            IList <Peer> peers = Peer.Decode(message.Added);
            var          count = id.TorrentManager.AddPeersCore(peers);

            id.TorrentManager.RaisePeersFound(new PeerExchangePeersAdded(id.TorrentManager, count, peers.Count, id));
        }
示例#14
0
        private void GetPeersCompleted(object o, TaskCompleteEventArgs e)
        {
            try
            {
                _activeQueries--;
                e.Task.Completed -= GetPeersCompleted;

                var args = (SendQueryEventArgs)e;

                // We want to keep a list of the top (K) closest nodes which have responded
                var target = ((SendQueryTask)args.Task).Target;

                //var index = ClosestActiveNodes.Values.IndexOf(target);

                var key   = target.Id.Xor(_infoHash);
                int index = 0;
                foreach (var obj3 in this.ClosestActiveNodes.Keys)
                {
                    if (!(obj3 == key))
                    {
                        ++index;
                    }
                    else
                    {
                        break;
                    }
                }

                if (index >= Bucket.MaxCapacity || args.TimedOut)
                {
                    ClosestActiveNodes.RemoveAt(index);
                }

                if (args.TimedOut)
                {
                    return;
                }

                var 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!
                    Debug.WriteLine("Found peers");
                    _engine.RaisePeersFound(_infoHash, Peer.Decode(response.Values));
                }
                else if (response.Nodes != null)
                {
                    if (!Active)
                    {
                        return;
                    }
                    // We got a list of nodes which are closer
                    var newNodes = Node.FromCompactNode(response.Nodes);
                    foreach (var n in Node.CloserNodes(_infoHash, _closestNodes, newNodes, Bucket.MaxCapacity))
                    {
                        SendGetPeers(n);
                    }
                }
            }
            finally
            {
                if (_activeQueries == 0)
                {
                    RaiseComplete(new TaskCompleteEventArgs(this));
                }
            }
        }