package call; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import call.SocketUtil.RequestType; public class PingClient extends AbstractClient implements Runnable { private static final String PING = "PING"; private static final Map<Contact, Ping> pings = new HashMap<>(); private static final Map<Contact, List<Listener>> listeners = new HashMap<>(); private final PrintWriter out; private final BufferedReader in; private final boolean isServer; public PingClient(String host, int port) throws UnknownHostException, IOException { super(host, port, RequestType.Ping); out = new PrintWriter(socket.getOutputStream()); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); isServer = false; } public PingClient(Contact contact) throws UnknownHostException, IOException { super(contact, RequestType.Ping); out = new PrintWriter(socket.getOutputStream()); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); isServer = false; } public PingClient(Contact contact, Socket socket, List<String> headers) throws IOException { super(contact, socket, headers, RequestType.Ping); out = new PrintWriter(socket.getOutputStream()); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); isServer = true; } @Override public void run() { long average = 0; long times = 0; long best = 0; long worst = 0; try { for (int i = 0; i < 20 && !socket.isClosed(); ++i) { long ms = ping(i == 0); if (ms > 0) { ++times; average += ms; if (ms > worst || worst == 0) worst = ms; if (ms < best || best == 0) best = ms; } } socket.close(); } catch (IOException e) { e.printStackTrace(); } if (times > 0) { average = (long) ((double) (average) / (double) (times)); long uptime = Long.parseLong(SocketUtil.getHeaderValue(headers, "uptime")); Ping ping = new Ping(average, best, worst, uptime); pings.put(contact, ping); notifyListeners(contact); //Util.msg(contact).println("Ping: " + ping.getId() + " ms", Color.PINK); } } private long ping(boolean isFirstPing) throws IOException { long starttime = System.currentTimeMillis(); if (!(isFirstPing && isServer)) { // Util.log(contact, "written: ping"); out.println(PING); out.flush(); } String line; while (!socket.isClosed() && (line = in.readLine()) != null) { if (line.contains(PING)) { // Util.log(contact, "recieved: pong"); long stoptime = System.currentTimeMillis(); return stoptime - starttime; } else { Util.log(contact, "WTF?! " + line); } } return 0; } public static Ping getPing(Contact contact) { return pings.containsKey(contact) ? pings.get(contact) : null; } @Override public String getId() { return "PingClient<" + contact.getId() + ">"; } private static void notifyListeners(Contact contact) { if (listeners.containsKey(contact)) { List<Listener> list = listeners.get(contact); for (Listener listener : list) { listener.onPingUpdate(contact); } } } public static void addListener(Contact contact, Listener listener) { if (listeners.containsKey(contact)) { List<Listener> list = listeners.get(contact); list.add(listener); listeners.put(contact, list); } else { List<Listener> list = new ArrayList<>(); list.add(listener); listeners.put(contact, list); } PingScanner.resetWaitTime(); } public static interface Listener { void onPingUpdate(Contact contact); } }