From c8a46dac5d1b6913d79cfa1cfcbc72763fa4d174 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Wed, 29 Aug 2012 13:45:29 +0000 Subject: [PATCH] i2psnark: - Add new flood-resistant KBucket trim policy - Limit received MsgID size --- .../src/org/klomp/snark/dht/DHTNodes.java | 4 +- .../src/org/klomp/snark/dht/KBTrimmer.java | 37 +++++++++++++++++++ .../java/src/org/klomp/snark/dht/MsgID.java | 5 +++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 apps/i2psnark/java/src/org/klomp/snark/dht/KBTrimmer.java 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 1b2ae428e7..64a650bae8 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/dht/DHTNodes.java +++ b/apps/i2psnark/java/src/org/klomp/snark/dht/DHTNodes.java @@ -46,13 +46,15 @@ class DHTNodes { private static final int MAX_PEERS = 799; /** Buckets older than this are refreshed - BEP 5 says 15 minutes */ private static final long MAX_BUCKET_AGE = 15*60*1000; + private static final int KAD_K = 8; + private static final int KAD_B = 1; public DHTNodes(I2PAppContext ctx, NID me) { _context = ctx; _expireTime = MAX_EXPIRE_TIME; _log = _context.logManager().getLog(DHTNodes.class); _nodeMap = new ConcurrentHashMap(); - _kad = new KBucketSet(ctx, me, 8, 1); + _kad = new KBucketSet(ctx, me, KAD_K, KAD_B, new KBTrimmer(ctx, KAD_K)); } public void start() { diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/KBTrimmer.java b/apps/i2psnark/java/src/org/klomp/snark/dht/KBTrimmer.java new file mode 100644 index 0000000000..96809cbc21 --- /dev/null +++ b/apps/i2psnark/java/src/org/klomp/snark/dht/KBTrimmer.java @@ -0,0 +1,37 @@ +package org.klomp.snark.dht; + +import java.util.Set; + +import net.i2p.I2PAppContext; +import net.i2p.kademlia.KBucket; +import net.i2p.kademlia.KBucketSet; + +/** + * Removes an element older than 15 minutes, but only if the bucket hasn't changed in 5 minutes. + */ +class KBTrimmer implements KBucketSet.KBucketTrimmer<NID> { + private final I2PAppContext _ctx; + private final int _max; + + private static final long MIN_BUCKET_AGE = 5*60*1000; + private static final long MAX_NODE_AGE = 15*60*1000; + + public KBTrimmer(I2PAppContext ctx, int max) { + _ctx = ctx; + _max = max; + } + + public boolean trim(KBucket<NID> kbucket, NID toAdd) { + long now = _ctx.clock().now(); + if (kbucket.getLastChanged() > now - MIN_BUCKET_AGE) + return false; + Set<NID> entries = kbucket.getEntries(); + for (NID nid : entries) { + if (nid.lastSeen() < now - MAX_NODE_AGE) { + if (kbucket.remove(nid)) + return true; + } + } + return entries.size() < _max; + } +} diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/MsgID.java b/apps/i2psnark/java/src/org/klomp/snark/dht/MsgID.java index 6d53f7c8fb..c28fba5c70 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/dht/MsgID.java +++ b/apps/i2psnark/java/src/org/klomp/snark/dht/MsgID.java @@ -14,7 +14,9 @@ import net.i2p.data.ByteArray; */ class MsgID extends ByteArray { + /** BEP 5: 2 bytes, incremented */ private static final int MY_TOK_LEN = 8; + private static final int MAX_TOK_LEN = 16; /** outgoing - generate a random ID */ public MsgID(I2PAppContext ctx) { @@ -28,5 +30,8 @@ class MsgID extends ByteArray { /** incoming - save the ID (arbitrary length) */ public MsgID(byte[] data) { super(data); + // lets not get carried away + if (data.length > MAX_TOK_LEN) + throw new IllegalArgumentException(); } } -- GitLab