package lbms.plugins.mldht.kad; import static the8472.utils.Functional.unchecked; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.util.Objects; import java.util.stream.IntStream; import java.util.stream.Stream; import lbms.plugins.mldht.kad.DHT.DHTtype; import the8472.bencode.BEncoder.StringWriter; public interface NodeList { enum AddressType { V4, V6; } AddressType type(); Stream<KBucketEntry> entries(); int packedSize(); default StringWriter writer() { return new StringWriter() { @Override public void writeTo(ByteBuffer buf) { entries().forEach(e -> { InetSocketAddress sockAddr = e.getAddress(); InetAddress addr = sockAddr.getAddress(); buf.put(e.getID().hash); buf.put(addr.getAddress()); buf.putShort((short) sockAddr.getPort()); }); } @Override public int length() { return packedSize(); } }; } static NodeList fromBuffer(ByteBuffer src, AddressType type) { Objects.requireNonNull(src); Objects.requireNonNull(type); return new NodeList() { @Override public int packedSize() { return src.remaining(); } @Override public Stream<KBucketEntry> entries() { ByteBuffer buf = src.slice(); byte[] rawId = new byte[20]; byte[] rawAddr = new byte[type == AddressType.V4 ? 4 : 16]; return IntStream.range(0, packedSize()/(type == AddressType.V4 ? DHTtype.IPV4_DHT.NODES_ENTRY_LENGTH : DHTtype.IPV6_DHT.NODES_ENTRY_LENGTH)).mapToObj(i -> { buf.get(rawId); buf.get(rawAddr); int port = Short.toUnsignedInt(buf.getShort()); InetAddress addr = unchecked(() -> InetAddress.getByAddress(rawAddr)); Key id = new Key(rawId); return new KBucketEntry(unchecked(() -> new InetSocketAddress(addr, port)), id); }); } @Override public StringWriter writer() { return new StringWriter() { @Override public void writeTo(ByteBuffer buf) { buf.put(src.slice()); } @Override public int length() { return src.remaining(); } }; } @Override public AddressType type() { return type; } }; } }