diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java
index 01b6a829b1550561d9c6ce9ac261340e27b9926e..ac5c5328550fbac8b66e208ad01654926b976a21 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java
@@ -374,7 +374,8 @@ public class TrackerClient extends I2PAppThread
                 // announce  ourselves while the token is still good
                 // FIXME this needs to be in its own thread
                 if (!stop) {
-                    int good = _util.getDHT().announce(snark.getInfoHash(), 8, 5*60*1000);
+                    // announce only to the 1 closest
+                    int good = _util.getDHT().announce(snark.getInfoHash(), 1, 5*60*1000);
                     _util.debug("Sent " + good + " good announces to DHT", Snark.INFO);
                 }
 
diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/DHTNodes.java b/apps/i2psnark/java/src/org/klomp/snark/dht/DHTNodes.java
index 14c9f9a3fd69c8e1d62fe8494c082c3b0b6a7e8a..0e57d1f26a69e8b17a5b0ff4d16d3501b9c2ac12 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/dht/DHTNodes.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/dht/DHTNodes.java
@@ -39,7 +39,7 @@ class DHTNodes extends ConcurrentHashMap<NID, NodeInfo> {
     private static final long MAX_EXPIRE_TIME = 60*60*1000;
     private static final long MIN_EXPIRE_TIME = 5*60*1000;
     private static final long DELTA_EXPIRE_TIME = 7*60*1000;
-    private static final int MAX_PEERS = 9999;
+    private static final int MAX_PEERS = 999;
 
     public DHTNodes(I2PAppContext ctx) {
         super();
diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/DHTTracker.java b/apps/i2psnark/java/src/org/klomp/snark/dht/DHTTracker.java
index 712b89e4f0f34745ec5c90a5f3d39e459a128fbd..d7e9df93ed1ace2eacf9d0ca2e7768dd7abefd82 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/dht/DHTTracker.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/dht/DHTTracker.java
@@ -34,7 +34,7 @@ class DHTTracker {
     private static final long MAX_EXPIRE_TIME = 95*60*1000;
     private static final long MIN_EXPIRE_TIME = 5*60*1000;
     private static final long DELTA_EXPIRE_TIME = 7*60*1000;
-    private static final int MAX_PEERS = 9999;
+    private static final int MAX_PEERS = 2000;
 
     DHTTracker(I2PAppContext ctx) {
         _context = ctx;
diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java b/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java
index c4190bd3b4e5e9e5c883f400bf6b9e6ab293d347..f34a6a1dda8457afa5eac83fd764da64d552759d 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java
@@ -92,7 +92,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
     /** index to sent queries awaiting reply */
     private final ConcurrentHashMap<MsgID, ReplyWaiter> _sentQueries;
     /** index to outgoing tokens we generated, sent in reply to a get_peers query */
-    private final ConcurrentHashMap<Token, NID> _outgoingTokens;
+    private final ConcurrentHashMap<Token, NodeInfo> _outgoingTokens;
     /** index to incoming opaque tokens, received in a peers or nodes reply */
     private final ConcurrentHashMap<NID, Token> _incomingTokens;
 
@@ -148,8 +148,9 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
         _incomingTokens = new ConcurrentHashMap();
 
         // Construct my NodeInfo
-        // ports can really be fixed, just do this for testing
-        _qPort = 30000 + ctx.random().nextInt(99);
+        // Pick ports over a big range to marginally increase security
+        // If we add a search DHT, adjust to stay out of each other's way
+        _qPort = 2555 + ctx.random().nextInt(61111);
         _rPort = _qPort + 1;
         _myID = new byte[NID.HASH_LENGTH];
         ctx.random().nextBytes(_myID);
@@ -291,6 +292,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
 
     /**
      *  Get peers for a torrent.
+     *  This is an iterative lookup in the DHT.
      *  Blocking!
      *  Caller should run in a thread.
      *
@@ -404,13 +406,16 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
     }
 
     /**
-     *  Announce to the closest DHT peers.
+     *  Announce to the closest peers in the local DHT.
+     *  This is NOT iterative - call getPeers() first to get the closest
+     *  peers into the local DHT.
      *  Blocking unless maxWait <= 0
      *  Caller should run in a thread.
      *  This also automatically announces ourself to our local tracker.
      *  For best results do a getPeers() first so we have tokens.
      *
      *  @param ih the Info Hash (torrent)
+     *  @param max maximum number of peers to announce to
      *  @param maxWait the maximum total time to wait (ms) or 0 to do all in parallel and return immediately.
      *  @return the number of successful announces, not counting ourselves.
      */
@@ -842,6 +847,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
         }
 
         try {
+            // TODO I2CP per-packet options
             boolean success = _session.sendMessage(dest, payload, 0, payload.length, null, null, 60*1000,
                                                    repliable ? I2PSession.PROTO_DATAGRAM : I2PSession.PROTO_DATAGRAM_RAW,
                                                    fromPort, toPort);
@@ -1041,7 +1047,7 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
              _log.info("Rcvd get_peers from: " + nInfo + " for: " + ih);
         // generate and save random token
         Token token = new Token(_context);
-        _outgoingTokens.put(token, nInfo.getNID());
+        _outgoingTokens.put(token, nInfo);
         if (_log.shouldLog(Log.INFO))
              _log.info("Stored new OB token: " + token + " for: " + nInfo);
 
@@ -1074,20 +1080,14 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
      */
     private void receiveAnnouncePeer(MsgID msgID, InfoHash ih, byte[] tok) throws InvalidBEncodingException {
         Token token = new Token(tok);
-        NID nid = _outgoingTokens.get(token);
-        if (nid == null) {
+        NodeInfo nInfo = _outgoingTokens.get(token);
+        if (nInfo == null) {
             if (_log.shouldLog(Log.WARN))
                 _log.warn("Unknown token in announce_peer: " + token);
             if (_log.shouldLog(Log.INFO))
                 _log.info("Current known tokens: " + _outgoingTokens.keySet());
             return;
         }
-        NodeInfo nInfo = _knownNodes.get(nid);
-        if (nInfo == null) {
-            if (_log.shouldLog(Log.WARN))
-                _log.warn("Unknown node in announce_peer for: " + nid);
-            return;
-        }
         if (_log.shouldLog(Log.INFO))
              _log.info("Rcvd announce from: " + nInfo + " for: " + ih);