package the8472.mldht.cli.commands; import static the8472.bencode.Utils.hex2ary; import the8472.bencode.Utils; import the8472.mldht.cli.CommandProcessor; import lbms.plugins.mldht.kad.DHT; import lbms.plugins.mldht.kad.RPCCall; import lbms.plugins.mldht.kad.RPCCallListener; import lbms.plugins.mldht.kad.RPCServer; import lbms.plugins.mldht.kad.messages.MessageBase; import lbms.plugins.mldht.kad.messages.PingRequest; import lbms.plugins.mldht.kad.utils.AddressUtils; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.Optional; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Ping extends CommandProcessor { InetSocketAddress target; ScheduledThreadPoolExecutor timer = new ScheduledThreadPoolExecutor(1); { timer.setKeepAliveTime(2, TimeUnit.SECONDS); timer.allowCoreThreadTimeOut(true); } AtomicInteger iteration = new AtomicInteger(); @Override protected void process() { InetAddress addr; int port; try { String ip = arguments.get(0); Matcher m = Pattern.compile("^(?:0x)?(\\p{XDigit}+)$").matcher(ip); if(m.matches()) { String hex = m.group(1); byte[] raw = hex2ary(hex); InetSocketAddress sockaddr = AddressUtils.unpackAddress(raw); addr = sockaddr.getAddress(); port = sockaddr.getPort(); } else { port = Integer.valueOf(arguments.get(1)); addr = InetAddress.getByName(ip); } } catch (Exception e) { handleException(e); return; } target = new InetSocketAddress(addr, port); println("PING " + target); doPing(); } void doPing() { if(!isRunning()) return; Optional<DHT> dht = dhts.stream().filter(d -> d.getType().PREFERRED_ADDRESS_TYPE == target.getAddress().getClass()).findAny(); if(!dht.isPresent()) { printErr("no dht with an address type matching " + target.getAddress() + " found"); exit(1); } RPCServer srv = dht.get().getServerManager().getRandomActiveServer(true); PingRequest req = new PingRequest(); req.setDestination(target); RPCCall call = new RPCCall(req); call.addListener(new RPCCallListener() { int counter = iteration.incrementAndGet(); @Override public void onTimeout(RPCCall c) { println("#"+counter+": timed out"); timer.schedule(Ping.this::doPing, 1, TimeUnit.SECONDS); } @Override public void onStall(RPCCall c) {} @Override public void onResponse(RPCCall c, MessageBase rsp) { println("#"+counter+" response time=" + c.getRTT() + "ms " + rsp.getID() + rsp.getVersion().map(v -> " ver:" + Utils.prettyPrint(v)).orElse("")); timer.schedule(Ping.this::doPing, 1, TimeUnit.SECONDS); } }); srv.doCall(call); } }