package lbms.plugins.mldht.kad; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static the8472.utils.Functional.unchecked; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.Collection; import java.util.Collections; import java.util.concurrent.Executors; import org.junit.Before; import org.junit.Test; import lbms.plugins.mldht.kad.DHT.DHTtype; import lbms.plugins.mldht.kad.Node.RoutingTableEntry; import lbms.plugins.mldht.kad.messages.PingRequest; import lbms.plugins.mldht.kad.messages.PingResponse; import the8472.utils.io.NetMask; public class OnInsertValidations { Node node; Key nodeId; @Before public void setup() { DHT dht = new DHT(DHTtype.IPV6_DHT); dht.populate(); dht.setScheduler(Executors.newScheduledThreadPool(0)); node = dht.getNode(); node.initKey(null); nodeId = node.registerId(); } private PingResponse buildResponse(Key k, InetSocketAddress origin) { PingRequest req = new PingRequest(); RPCCall call = new RPCCall(req); PingResponse rsp = new PingResponse(new byte[0]); rsp.setAssociatedCall(call); rsp.setID(k); rsp.setOrigin(origin); return rsp; } @Test public void testImmediateEvictionOnIdMismatch() { NodeFactory.fillTable(node); KBucket bucket = node.table().get(0).getBucket(); KBucketEntry entry = bucket.randomEntry().get(); PingResponse rsp = buildResponse(Key.createRandomKey(), entry.getAddress()); rsp.getAssociatedCall().setExpectedID(entry.getID()); node.recieved(rsp); assertFalse(bucket.findByIPorID(entry.getAddress().getAddress(), entry.getID()).isPresent()); assertFalse(bucket.findByIPorID(null, rsp.getID()).isPresent()); } @Test public void testRTTPreference() { NodeFactory.fillTable(node); Collection<Key> localIds = node.localIDs(); RoutingTableEntry nonLocalFullBucket = node.table().stream().filter(e -> e.prefix.depth == 1).findAny().get(); Key newId = nonLocalFullBucket.prefix.createRandomKeyFromPrefix(); PingResponse rsp = buildResponse(newId, new InetSocketAddress(NodeFactory.generateIp((byte)0x00), 1234)); node.recieved(rsp); // doesn't get inserted because the replacement buckets only overwrite entries once every second and the main bucket is stable anyway assertFalse(nonLocalFullBucket.getBucket().getEntries().stream().anyMatch(e -> e.getID().equals(newId))); assertFalse(nonLocalFullBucket.getBucket().getReplacementEntries().stream().anyMatch(e -> e.getID().equals(newId))); long now = System.currentTimeMillis(); RPCCall call = rsp.getAssociatedCall(); call.sentTime = now - 50; call.responseTime = now; node.recieved(rsp); // main bucket accepts one RTT-based replacement for the youngest entry assertTrue(nonLocalFullBucket.getBucket().getEntries().stream().anyMatch(e -> e.getID().equals(newId))); Key anotherId = nonLocalFullBucket.prefix.createRandomKeyFromPrefix(); rsp = buildResponse(anotherId, new InetSocketAddress(NodeFactory.generateIp((byte)0x00), 1234)); call = rsp.getAssociatedCall(); call.sentTime = now - 50; call.responseTime = now; node.recieved(rsp); // replacement bucket accepts RTT-based overwrite once main bucket is satisfied assertTrue(nonLocalFullBucket.getBucket().getReplacementEntries().stream().anyMatch(e -> e.getID().equals(anotherId))); } @Test public void testTrustedNodes() { NodeFactory.fillTable(node); Collection<Key> localIds = node.localIDs(); RoutingTableEntry nonLocalFullBucket = node.table().stream().filter(e -> e.prefix.depth == 1).findAny().get(); PingRequest req = new PingRequest(); RPCCall call = new RPCCall(req); PingResponse rsp = new PingResponse(new byte[0]); rsp.setAssociatedCall(call); Key newId = nonLocalFullBucket.prefix.createRandomKeyFromPrefix(); rsp.setID(newId); rsp.setOrigin(new InetSocketAddress(NodeFactory.generateIp((byte)0x02), 1234)); node.recieved(rsp); assertFalse(node.table().stream().anyMatch(e -> e.getBucket().findByIPorID(null, newId).isPresent())); byte[] addr = new byte[16]; addr[0] = 0x20; addr[1] = 0x01; addr[2] = 0x20; addr[3] = 0x02; NetMask mask = new NetMask(unchecked(() -> InetAddress.getByAddress(addr)), 32); node.setTrustedNetMasks(Collections.singleton(mask)); node.recieved(rsp); assertTrue(node.table().stream().anyMatch(e -> e.getBucket().findByIPorID(null, newId).isPresent())); } }