diff --git a/history.txt b/history.txt index 29bd7ca09..e86f6404a 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,8 @@ +2008-03-08 zzz + * ClientPeerSelector: Implement strict ordering of peers, + based on XOR distance from a random hash + separately generated for each tunnel pool + 2008-03-07 zzz * Naming: Optimize lookups for a destkey * ProfileOrganizer, TunnelPoolSettings, ClientPeerSelector: diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index b54357532..bfcf50e73 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -17,7 +17,7 @@ import net.i2p.CoreVersion; public class RouterVersion { public final static String ID = "$Revision: 1.548 $ $Date: 2008-02-10 15:00:00 $"; public final static String VERSION = "0.6.1.31"; - public final static long BUILD = 3203; + public final static long BUILD = 3204; public static void main(String args[]) { System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("Router ID: " + RouterVersion.ID); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/PeerSelector.java b/router/java/src/net/i2p/router/networkdb/kademlia/PeerSelector.java index 8be6bfb8c..0d3aa52b7 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/PeerSelector.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/PeerSelector.java @@ -25,7 +25,7 @@ import net.i2p.stat.Rate; import net.i2p.stat.RateStat; import net.i2p.util.Log; -class PeerSelector { +public class PeerSelector { protected Log _log; protected RouterContext _context; @@ -180,7 +180,7 @@ class PeerSelector { peerHashes.removeAll(failing); } - protected BigInteger getDistance(Hash targetKey, Hash routerInQuestion) { + public static BigInteger getDistance(Hash targetKey, Hash routerInQuestion) { // plain XOR of the key and router byte diff[] = DataHelper.xor(routerInQuestion.getData(), targetKey.getData()); return new BigInteger(1, diff); diff --git a/router/java/src/net/i2p/router/tunnel/pool/ClientPeerSelector.java b/router/java/src/net/i2p/router/tunnel/pool/ClientPeerSelector.java index 159dc28fe..fc5871b14 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/ClientPeerSelector.java +++ b/router/java/src/net/i2p/router/tunnel/pool/ClientPeerSelector.java @@ -28,8 +28,8 @@ class ClientPeerSelector extends TunnelPeerSelector { matches.remove(ctx.routerHash()); ArrayList rv = new ArrayList(matches); - // Todo - Rather than shuffle, sort using xor distance from settings.getRandomKey() - Collections.shuffle(rv, ctx.random()); + if (rv.size() > 1) + orderPeers(rv, settings.getRandomKey()); if (settings.isInbound()) rv.add(0, ctx.routerHash()); else diff --git a/router/java/src/net/i2p/router/tunnel/pool/ExploratoryPeerSelector.java b/router/java/src/net/i2p/router/tunnel/pool/ExploratoryPeerSelector.java index 3a8bcfd13..25e0378b6 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/ExploratoryPeerSelector.java +++ b/router/java/src/net/i2p/router/tunnel/pool/ExploratoryPeerSelector.java @@ -43,7 +43,8 @@ class ExploratoryPeerSelector extends TunnelPeerSelector { matches.remove(ctx.routerHash()); ArrayList rv = new ArrayList(matches); - Collections.shuffle(rv, ctx.random()); + if (rv.size() > 1) + orderPeers(rv, settings.getRandomKey()); if (settings.isInbound()) rv.add(0, ctx.routerHash()); else diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java index 78a44beb5..3d4a0b9a5 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPeerSelector.java @@ -1,12 +1,14 @@ package net.i2p.router.tunnel.pool; import java.util.*; +import java.math.BigInteger; import net.i2p.I2PAppContext; import net.i2p.data.*; import net.i2p.router.Router; import net.i2p.router.RouterContext; import net.i2p.router.TunnelPoolSettings; import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade; +import net.i2p.router.networkdb.kademlia.PeerSelector; import net.i2p.router.peermanager.PeerProfile; import net.i2p.util.Log; @@ -449,4 +451,21 @@ public abstract class TunnelPeerSelector { //System.err.println("Filter unreachable? " + rv + " (inbound? " + isInbound + ", exploratory? " + isExploratory); return rv; } + + protected void orderPeers(List rv, Hash hash) { + Collections.sort(rv, new HashComparator(hash)); + } + + private class HashComparator implements Comparator { + private Hash _hash; + + private HashComparator(Hash h) { + _hash = h; + } + public int compare(Object l, Object r) { + BigInteger ll = PeerSelector.getDistance(_hash, (Hash) l); + BigInteger rr = PeerSelector.getDistance(_hash, (Hash) r); + return ll.compareTo(rr); + } + } }