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)); } }
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); }
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)); }
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()); } }
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)); } } }
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; } } }
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"); }
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); }
public void DecodeList() { // List of String BEncodedList list = new BEncodedList(); foreach (Peer p in _peers) { list.Add((BEncodedString)p.CompactPeer()); } VerifyDecodedPeers(Peer.Decode(list)); }
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"); }
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)); }
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"); }
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)); }
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)); } } }