Skip to content

Commit

Permalink
Only nodes which are closer than previously queried nodes will be que…
Browse files Browse the repository at this point in the history
…ried. Always query nodes which are returned as part of a GetPeersResponse.

svn path=/trunk/bitsharp/; revision=113482
  • Loading branch information
alanmcgovern committed Sep 18, 2008
1 parent f430095 commit 4e28cad
Showing 1 changed file with 38 additions and 18 deletions.
56 changes: 38 additions & 18 deletions src/MonoTorrent.Dht/MonoTorrent.Dht/Tasks/AnnounceTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ internal class AnnounceTask : Task
{
NodeId infoHash;
DhtEngine engine;
List<Node> nodes;
SortedList<NodeId, NodeId> closestNodes;

public AnnounceTask(DhtEngine engine, byte[] infohash)
: this(engine, new NodeId(infohash))
{
Expand All @@ -21,7 +21,7 @@ public AnnounceTask(DhtEngine engine, NodeId infohash)
{
this.engine = engine;
this.infoHash = infohash;
this.nodes = new List<Node>(24);
this.closestNodes = new SortedList<NodeId, NodeId>(Bucket.MaxCapacity);
DhtEngine.MainLoop.QueueTimeout(TimeSpan.FromMinutes(1), delegate {
RaiseComplete(new TaskCompleteEventArgs(this));
return false;
Expand All @@ -34,15 +34,19 @@ public override void Execute()
return;

Active = true;
engine.RoutingTable.NodeAdded += NodeFound;


foreach (Node n in engine.RoutingTable.GetClosest(infoHash))
{
closestNodes.Add(n.Id.Xor(infoHash), n.Id);
SendGetPeers(n);
}
}

private void SendGetPeers(Node n)
{
nodes.Add(n);
if (!Active)
return;

GetPeers m = new GetPeers(engine.RoutingTable.LocalNode.Id, infoHash);
SendQueryTask task = new SendQueryTask(engine, m, n);
task.Completed += GetPeersCompleted;
Expand All @@ -53,37 +57,53 @@ private void GetPeersCompleted(object o, TaskCompleteEventArgs e)
{
SendQueryEventArgs args = (SendQueryEventArgs)e;
e.Task.Completed -= GetPeersCompleted;

GetPeersResponse response = (GetPeersResponse)args.Response;
Node node = nodes.Find(delegate(Node n) { return n.Id == response.Id; });
nodes.Remove(node);

if (args.TimedOut)
return;

GetPeersResponse response = (GetPeersResponse)args.Response;
if (response.Values != null)
{
// We have actual peers!
engine.RaisePeersFound(node, infoHash, MonoTorrent.Client.Peer.Decode(response.Values));
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
foreach (Node n in Node.FromCompactNode(response.Nodes))
{
// If we attempt to add a node to the engine, if the
// bucket is already full it will be silently dropped.
// Therefore we should always just send a getpeers message
// without bothering to verify the node is still alive
engine.Add(n);

// Only bother pinging the node if it's closer
// than everything else we've tried.
NodeId distance = n.Id.Xor(infoHash);
if (closestNodes.Count < Bucket.MaxCapacity)
{
closestNodes.Add(distance, n.Id);
SendGetPeers(n);
}
else if(distance < closestNodes.Keys[closestNodes.Count - 1])
{
closestNodes.RemoveAt(closestNodes.Count - 1);
closestNodes.Add(distance, n.Id);
SendGetPeers(n);
}
}
}
}

public void NodeFound(object sender, NodeAddedEventArgs e)
{
nodes.Add(e.Node);
SendGetPeers(e.Node);
}

protected override void RaiseComplete(TaskCompleteEventArgs e)
{
if (!Active)
return;

Active = false;
engine.RoutingTable.NodeAdded -= NodeFound;
base.RaiseComplete(e);
}
}
Expand Down

0 comments on commit 4e28cad

Please sign in to comment.