/* * Test for an echo server. This test is intended to be used via an * I2PTunnel, but should work as well on other networks that provide * TCP tunneling and an echo server. * * Copyright (c) 2004 Michael Schierl * * Licensed unter GNU General Public License. */ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Writer; import java.net.ConnectException; import java.net.Socket; import java.net.SocketException; /** * The main engine for the EchoTester. */ public class EchoTester extends Thread { /** * How long to wait between packets. Default is 6 seconds. */ private static long PACKET_DELAY = 6000; /** * How many packets may be on the way before the connection is * seen as "broken" and disconnected. */ private static final long MAX_PACKETS_QUEUED = 50; // unused private EchoTestAnalyzer eta; private String host; private int port; // the following vars are synchronized via the lock. private Object lock = new Object(); private long nextPacket = 0; private long nextUnreceived = 0; private boolean readerRunning = false; public static void main(String[] args) { if (args.length == 3) PACKET_DELAY = Long.parseLong(args[2]); new EchoTester(args[0], Integer.parseInt(args[1]), new BasicEchoTestAnalyzer()); } public EchoTester(String host, int port, EchoTestAnalyzer eta) { this.eta = eta; this.host = host; this.port = port; start(); } public void run() { try { while (true) { Socket s; try { s = new Socket(host, port); } catch (ConnectException ex) { eta.disconnected(true); Thread.sleep(PACKET_DELAY); continue; } System.out.println("41: Connected to " + host + ":" + port); synchronized (lock) { nextUnreceived = nextPacket; } Thread t = new ResponseReaderThread(s); Writer w = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); while (true) { long no; synchronized (lock) { no = nextPacket++; } try { w.write(no + " " + System.currentTimeMillis() + "\n"); w.flush(); } catch (SocketException ex) { break; } Thread.sleep(PACKET_DELAY); } s.close(); t.join(); synchronized (lock) { if (readerRunning) { System.out.println("*** WHY IS THIS THREAD STILL" + " RUNNING?"); } while (nextUnreceived < nextPacket) { nextUnreceived++; eta.packetLossOccurred(true); } if (nextUnreceived > nextPacket) { System.out.println("*** WTF? " + nextUnreceived + " > " + nextPacket); } } eta.disconnected(false); } } catch (InterruptedException ex) { ex.printStackTrace(); System.exit(1); // treat these errors as fatal } catch (IOException ex) { ex.printStackTrace(); System.exit(1); // treat these errors as fatal } } private class ResponseReaderThread extends Thread { private Socket s; public ResponseReaderThread(Socket s) { this.s = s; synchronized (lock) { readerRunning = true; } start(); } public void run() { try { BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream())); String line; int index; while ((line = br.readLine()) != null) { if ((index = line.indexOf(" ")) == -1) continue; long now, packetNumber, packetTime; now = System.currentTimeMillis(); try { packetNumber = Long.parseLong(line.substring(0, index)); packetTime = Long.parseLong(line.substring(index + 1)); } catch (NumberFormatException ex) { System.out.println(ex.toString()); continue; } synchronized (lock) { while (packetNumber > nextUnreceived) { nextUnreceived++; eta.packetLossOccurred(false); } if (nextUnreceived > packetNumber) { System.out.println("*** DOUBLE PACKET!"); } else { nextUnreceived++; } } eta.successOccurred(now - packetTime); } } catch (SocketException ex) { // ignore } catch (IOException ex) { ex.printStackTrace(); System.exit(0); } synchronized (lock) { readerRunning = false; } } } }