
import java.io.*;
import java.net.*;

public class trw_Ping {
  static final int DEFAULT_PORT = 7;
  static final int UDP_HEADER = 20 + 8;
  static final int BACKSPACE = 8;

/*
  public static void main (String[] args) throws IOException {
    parseArgs (args);
    init ();
    for (int i = 0; (i < count) || (count == 0); ++ i) {
      long past = System.currentTimeMillis ();
      ping (i, past);
      try {
        pong (i, past);
      } catch (InterruptedIOException ignored) {
      }
    }
    socket.close ();
    printStats ();
  }
*/

	static String host = "24.207.159.20";
	static int port, count = 10, delay = 1000, size = 4000;

	static DatagramSocket socket = new DatagramSocket ();
	static byte[] outBuffer = new byte[Math.max (12, size - UDP_HEADER)];
	static DatagramPacket outPacket = new DatagramPacket (outBuffer, outBuffer.length,
                                    InetAddress.getByName (host), port);
	static byte[] inBuffer = new byte[outBuffer.length];
	static DatagramPacket inPacket = new DatagramPacket (inBuffer, inBuffer.length);

	static int sent = 0;

	for (int i = 0; (i < count) || (count == 0); ++ i) {
		long past = System.currentTimeMillis ();
		trw_ping (i, past);
		try {
			pong (i, past);
      } catch (InterruptedIOException ignored) {}
	}
	socket.close ();
	printStats ();

	static void trw_Ping (int seq, long past) throws IOException {
		writeInt (seq, outBuffer, 0);
		writeLong (past, outBuffer, 4);
		socket.send (outPacket);
		++ sent;
	}

	static final void writeInt (int datum, byte[] dst, int offset) {
		dst[offset] = (byte) (datum >> 24);
		dst[offset + 1] = (byte) (datum >> 16);
		dst[offset + 2] = (byte) (datum >> 8);
		dst[offset + 3] = (byte) datum;
	}

	static final void writeLong (long datum, byte[] dst, int offset) {
		writeInt ((int) (datum >> 32), dst, offset);
		writeInt ((int) datum, dst, offset + 4);
	}

	static int received = 0;

	static void pong (int seq, long past) throws IOException {
		long present = System.currentTimeMillis ();
		int tmpRTT = (maxRTT == 0) ? 500 : (int) maxRTT * 2;
		int wait = Math.max (delay, (seq == count - 1) ? tmpRTT : 0);
		do {
			socket.setSoTimeout (Math.max (1, wait - (int) (present - past)));
			socket.receive (inPacket);
			++ received;
			present = System.currentTimeMillis ();
			processPong (present);
		} while (present - past < wait);
	}

	static long minRTT = 100000, maxRTT = 0, totRTT = 0;

	static void processPong (long present) {
		int seq = readInt (inBuffer, 0);
		long when = readLong (inBuffer, 4);
		long rtt = present - when;
		System.out.write (BACKSPACE);
		System.out.flush ();
		if (rtt < minRTT) minRTT = rtt;
		if (rtt > maxRTT) maxRTT = rtt;
		totRTT += rtt;
	}

	static final int readInt (byte[] src, int offset) {
		return (src[offset] << 24) | ((src[offset + 1] & 0xff) << 16) |
			((src[offset + 2] & 0xff) << 8) | (src[offset + 3] & 0xff);
	}

	static final long readLong (byte[] src, int offset) {
		return ((long) readInt (src, offset) << 32) |
			((long) readInt (src, offset + 4) & 0xffffffffL);
	}

	public void printStats () {
		System.out.println
			(sent + " packets transmitted, " + received + " packets received, " +
			(100 * (sent - received) / sent) + "% packet loss");
		if (received > 0)
			System.out.println ("round-trip min/avg/max = " + minRTT + '/' +
				((float) totRTT / received) + '/' + maxRTT + " ms");
	}
}
