diff --git a/apps/heartbeat/doc/readme.gui.txt b/apps/heartbeat/doc/readme.gui.txt deleted file mode 100644 index fde06a336..000000000 --- a/apps/heartbeat/doc/readme.gui.txt +++ /dev/null @@ -1,39 +0,0 @@ -The Heartbeat GUI loads up the stat files generated by the Heartbeat -engine and renders them visually, offering a way to drill through different -data points and take snapshots as things change (by saving particular stat -files for later). The GUI itself doesn't need to be on the same machine -as the Heartbeat engine - it pulls the stat files through any URL - even -through the EepProxy. - -An example Heartbeat GUI config file follows - - # how often do we want to pull new data to render - refreshFrequency=60 - ## for each peer test we may want to include in the GUI: - # where to find the current stat file (URL or filename) - stat.0.location=http://dev.i2p.net/stats/heartbeatStat_khWY_30s_1kb.txt - ## optional entries for each peer test describing what we want shown - ## (and how we want it shown) - # do we want to plot the send time (from when the ping was sent until the pong server got it)? - stat.0.plot.current.send=true - # do we want to plot the receive time (from when the pong was sent until reception)? - stat.0.plot.current.receive=true - # do we want to plot the lost messages? - stat.0.plot.current.lost=true - # what color should the current lines be rendered in? - stat.0.plot.current.color=BLUE - ## optional entries for each peer test describing what averages we want - ## rendered - # plot 1 minute send average? - stat.0.plot.1m.send=true - # plot 1 minute receive average? - stat.0.plot.1m.receive=true - # plot 1 minute lost message average? - stat.0.plot.1m.lost=true - # what color should the 1 minute averages be rendered as? - stat.0.plot.1m.color=GREEN - ## repeated for all of the averaged periods, e.g. - ## stat.0.plot.30m, .60m, 1440m (1 day) - -There may be some other options, such as where to store snapshot files, whether -to generate PNG images, etc. \ No newline at end of file diff --git a/apps/heartbeat/doc/readme.txt b/apps/heartbeat/doc/readme.txt deleted file mode 100644 index d9b667a1a..000000000 --- a/apps/heartbeat/doc/readme.txt +++ /dev/null @@ -1,122 +0,0 @@ -Heartbeat - -Application layer tool for monitoring the long term health of the -network by periodically testing peers, generating stats, and -rendering them visually. The engine (both server and client) should -work headless and seperate from the GUI, exposing the data in a simple -to parse (and human readable) text file for each peer being tested. -The GUI then periodically refreshes itself by loading those files ( -either locally or from a URL) and renders the current state accordingly, -giving users a way to check that the network is alive, devs a tool to -both monitor the state of the network and to debug different situations (by -accessing the stat file - either live or archived). - -The heartbeat configuration file is organized as a standard properties -file (by default located at heartbeat.config, but that can be overridden by -passing a filename as the first argument to the Heartbeat command): - - # where the router is located (default is localhost) - i2cpHost=localhost - # I2CP port for the router (default is 7654) - i2cpPort=4001 - # How many hops we want the router to put in our tunnels (default is 2) - numHops=2 - # where our private destination keys are located - if this doesn't exist, - # a new one will be created and saved there (by default, heartbeat.keys) - privateDestinationFile=heartbeat_r2.keys - - ## peer tests configured below: - - # destination peer for test 0 - peer.0.peer=[destination in base64] - # where will we write out the stat data? - peer.0.statFile=heartbeatStat_khWY_30s_1kb.txt - # how many minutes will we keep stats for? - peer.0.statDuration=30 - # how often will we write out new stat data (in seconds)? - peer.0.statFrequency=60 - # how often will we send a ping to the peer (in seconds)? - peer.0.sendFrequency=30 - # how many bytes will be included in the ping? - peer.0.sendSize=1024 - # take a guess... - peer.0.comment=Test with localhost sending 1KB of data every 30 seconds - # we can keep track of a few moving averages - this value includes a whitespace - # delimited list of numbers, each specifying a period to calculate the average - # over (in minutes) - peer.0.averagePeriods=1 5 30 - ## repeat the peer.0.* for as many tests as desired, incrementing as necessary - -If there are no peer.* lines, it will simply run a pong server. If any data is -missing, it will use the defaults (though there are no defaults for peer.* lines) - -running the Heartbeat app with no heartbeat configuration file whatsoever will create -a new pong server (storing its keys at heartbeat.keys) and using the I2P router at -localhost:7654. - -The stat file generated for each set of peer.n.* lines contains the current state -of the test, its averages, as well as any other interesting data points. An example -stat file follows (hopefully it is self explanatory): - - peer khWYqCETu9YtPUvGV92ocsbEW5DezhKlIG7ci8RLX3g= - local u-9hlR1ik2hemXf0HvKMfeRgrS86CbNQh25e7XBhaQE= - peerDest [base 64 of the full destination] - localDest [base 64 of the full destination] - numTunnelHops 2 - comment Test with localhost sending 30KB every 20 seconds - sendFrequency 20 - sendSize 30720 - sessionStart 20040409.22:51:10.915 - currentTime 20040409.23:31:39.607 - numPending 2 - lifetimeSent 118 - lifetimeRecv 113 - #averages minutes sendMs recvMs numLost - periodAverage 1 1843 771 0 - periodAverage 5 786 752 1 - periodAverage 30 855 735 3 - #action status date and time sent sendMs replyMs - EVENT OK 20040409.23:21:44.742 691 670 - EVENT OK 20040409.23:22:05.201 671 581 - EVENT OK 20040409.23:22:26.301 1182 1452 - EVENT OK 20040409.23:22:47.322 24304 1723 - EVENT OK 20040409.23:23:08.232 2293 1081 - EVENT OK 20040409.23:23:29.332 1392 641 - EVENT OK 20040409.23:23:50.262 641 761 - EVENT OK 20040409.23:24:11.102 651 701 - EVENT OK 20040409.23:24:31.401 841 621 - EVENT OK 20040409.23:24:52.061 651 681 - EVENT OK 20040409.23:25:12.480 701 1623 - EVENT OK 20040409.23:25:32.990 1442 1212 - EVENT OK 20040409.23:25:54.230 591 631 - EVENT OK 20040409.23:26:14.620 620 691 - EVENT OK 20040409.23:26:35.199 1793 1432 - EVENT OK 20040409.23:26:56.570 661 641 - EVENT OK 20040409.23:27:17.200 641 660 - EVENT OK 20040409.23:27:38.120 611 921 - EVENT OK 20040409.23:27:58.699 831 621 - EVENT OK 20040409.23:28:19.559 801 661 - EVENT OK 20040409.23:28:40.279 601 611 - EVENT OK 20040409.23:29:00.648 601 621 - EVENT OK 20040409.23:29:21.288 701 661 - EVENT LOST 20040409.23:29:41.828 - EVENT LOST 20040409.23:30:02.327 - EVENT LOST 20040409.23:30:22.656 - EVENT OK 20040409.23:31:24.305 1843 771 - -The actual ping and pong messages sent are formatted trivially - -ping messages contain - $from $series $type $sentOn $size $payload -while pong messages contain - $from $series $type $sentOn $receivedOn $size $payload - -$series is a number describing the sending client's test (so that you can -ping the same peer with different configurations concurrently, varying things -like the frequency and size of the message, window, etc). - -They are sent as raw binary messages though, so see I2PAdapter.sendPing(..) -and I2PAdapter.sendPong(..) for the details. - -To get valid measurements, of course, you will want to make sure that -both the heartbeat client and pong server have synchronized clocks (even -more so than I2P requires). It is highly recommended that only NTP -synchronized peers be used for heartbeat tests. \ No newline at end of file diff --git a/apps/heartbeat/java/build.xml b/apps/heartbeat/java/build.xml deleted file mode 100644 index 99a627956..000000000 --- a/apps/heartbeat/java/build.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/ClientConfig.java b/apps/heartbeat/java/src/net/i2p/heartbeat/ClientConfig.java deleted file mode 100644 index 59b9dfc87..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/ClientConfig.java +++ /dev/null @@ -1,468 +0,0 @@ -package net.i2p.heartbeat; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Properties; -import java.util.StringTokenizer; - -import net.i2p.data.DataFormatException; -import net.i2p.data.Destination; -import net.i2p.util.Log; - -/** - * Define the configuration for testing against one particular peer as a client - */ -public class ClientConfig { - private static final Log _log = new Log(ClientConfig.class); - private Destination _peer; - private Destination _us; - private String _statFile; - private int _statDuration; - private int _statFrequency; - private int _sendFrequency; - private int _sendSize; - private int _numHops; - private String _comment; - private int _averagePeriods[]; - - /** - * @seeRoutine ClientConfig#load - * @seeRoutine ClientConfig#store - */ - public static final String PROP_PREFIX = "peer."; - - /** - * @seeRoutine ClientConfig#load - * @seeRoutine ClientConfig#store - */ - public static final String PROP_PEER = ".peer"; - - /** - * @seeRoutine ClientConfig#load - * @seeRoutine ClientConfig#store - */ - public static final String PROP_STATFILE = ".statFile"; - - /** - * @seeRoutine ClientConfig#load - * @seeRoutine ClientConfig#store - */ - public static final String PROP_STATDURATION = ".statDuration"; - - /** - * @seeRoutine ClientConfig#load - * @seeRoutine ClientConfig#store - */ - public static final String PROP_STATFREQUENCY = ".statFrequency"; - - /** - * @seeRoutine ClientConfig#load - * @seeRoutine ClientConfig#store - */ - public static final String PROP_SENDFREQUENCY = ".sendFrequency"; - - /** - * @seeRoutine ClientConfig#load - * @seeRoutine ClientConfig#store - */ - public static final String PROP_SENDSIZE = ".sendSize"; - - /** - * @seeRoutine ClientConfig#load - * @seeRoutine ClientConfig#store - */ - public static final String PROP_COMMENT = ".comment"; - - /** - * @seeRoutine ClientConfig#load - * @seeRoutine ClientConfig#store - */ - public static final String PROP_AVERAGEPERIODS = ".averagePeriods"; - - /** - * Default constructor... - */ - public ClientConfig() { - this(null, null, null, -1, -1, -1, -1, 0, null, null); - } - - /** - * Create a dummy client config to be fetched from the specified location - * @param location the location to fetch from - */ - public ClientConfig(String location) { - this(null, null, location, -1, -1, -1, -1, 0, null, null); - } - - /** - * @param peer who we will test against - * @param us who we are - * @param statLocation where the stat data should be stored/fetched - * @param duration how many minutes to keep events for - * @param statFreq how often to write out stats - * @param sendFreq how often to send pings - * @param sendSize how large the pings should be - * @param numHops how many hops is the current Heartbeat app using - * @param comment describe this test - * @param averagePeriods list of minutes to summarize over - */ - public ClientConfig(Destination peer, Destination us, String statLocation, int duration, int statFreq, int sendFreq, - int sendSize, int numHops, String comment, int averagePeriods[]) { - _peer = peer; - _us = us; - _statFile = statLocation; - _statDuration = duration; - _statFrequency = statFreq; - _sendFrequency = sendFreq; - _sendSize = sendSize; - _numHops = numHops; - _comment = comment; - _averagePeriods = averagePeriods; - } - - /** - * Retrieves the peer to test against - * - * @return the Destination (peer) - */ - public Destination getPeer() { - return _peer; - } - - /** - * Sets the peer to test against - * - * @param peer the Destination (peer) - */ - public void setPeer(Destination peer) { - _peer = peer; - } - - /** - * Retrieves who we are when we test - * - * @return the Destination (us) - */ - public Destination getUs() { - return _us; - } - - /** - * Sets who we are when we test - * - * @param us the Destination (us) - */ - public void setUs(Destination us) { - _us = us; - } - - /** - * Retrieves the location to write the current stats to - * - * @return the name of the file - */ - public String getStatFile() { - return _statFile; - } - - /** - * Sets the name of the location we write the current stats to - * - * @param statFile the name of the file - */ - public void setStatFile(String statFile) { - _statFile = statFile; - } - - /** - * Retrieves how many minutes of statistics should be maintained within the window for this client - * - * @return the number of minutes - */ - public int getStatDuration() { - return _statDuration; - } - - /** - * Sets how many minutes of statistics should be maintained within the window for this client - * - * @param durationMinutes the number of minutes - */ - public void setStatDuration(int durationMinutes) { - _statDuration = durationMinutes; - } - - /** - * Retrieves how frequently the stats are written out (in seconds) - * - * @return the frequency in seconds - */ - public int getStatFrequency() { - return _statFrequency; - } - - /** - * Sets how frequently the stats are written out (in seconds) - * - * @param freqSeconds the frequency in seconds - */ - public void setStatFrequency(int freqSeconds) { - _statFrequency = freqSeconds; - } - - /** - * Retrieves how frequenty we send messages to the peer (in seconds) - * - * @return the frequency in seconds - */ - public int getSendFrequency() { - return _sendFrequency; - } - - /** - * Sets how frequenty we send messages to the peer (in seconds) - * - * @param freqSeconds the frequency in seconds - */ - public void setSendFrequency(int freqSeconds) { - _sendFrequency = freqSeconds; - } - - /** - * Retrieves how many bytes the ping messages should be (min values ~700, max ~32KB) - * - * @return the size in bytes - */ - public int getSendSize() { - return _sendSize; - } - - /** - * Sets how many bytes the ping messages should be (min values ~700, max ~32KB) - * - * @param numBytes the size in bytes - */ - public void setSendSize(int numBytes) { - _sendSize = numBytes; - } - - /** - * Retrieves the brief, 1 line description of the test. Useful comments are along the lines of "The peer is located on a fast router and connection with 2 - * hop tunnels". - * - * @return the brief comment - */ - public String getComment() { - return _comment; - } - - /** - * Sets a brief, 1 line description (comment) of the test. - * - * @param comment the brief comment - */ - public void setComment(String comment) { - _comment = comment; - } - - /** - * Retrieves the periods that the client's tests should be averaged over. - * - * @return list of periods (in minutes) that the data should be averaged over, or null - */ - public int[] getAveragePeriods() { - return _averagePeriods; - } - - /** - * Sets the periods that the client's tests should be averaged over. - * - * @param periods the list of periods (in minutes) that the data should be averaged over, or null - */ - public void setAveragePeriods(int periods[]) { - _averagePeriods = periods; - } - - /** - * Make sure we're keeping track of the average over the given time period. - * - * @param minutes how many minutes to monitor - */ - public void addAveragePeriod(int minutes) { - if (_averagePeriods != null) { - for (int i = 0; i < _averagePeriods.length; i++) { - if (_averagePeriods[i] == minutes) - return; - } - } - - int numPeriods = 1; - if (_averagePeriods != null) - numPeriods += _averagePeriods.length; - int periods[] = new int[numPeriods]; - if (_averagePeriods != null) - System.arraycopy(_averagePeriods, 0, periods, 0, _averagePeriods.length); - periods[periods.length-1] = minutes; - Arrays.sort(periods); - _averagePeriods = periods; - } - - /** - * Retrieves how many hops this test engine is configured to use for its outbound and inbound tunnels - * - * @return the number of hops - */ - public int getNumHops() { - return _numHops; - } - - /** - * Sets how many hops this test engine is configured to use for its outbound and inbound tunnels - * - * @param numHops the number of hops - */ - public void setNumHops(int numHops) { - _numHops = numHops; - } - - /** - * Load the client config from the properties specified, deriving the current config entry from the peer number. - * - * @param clientConfig the properties to load from - * @param peerNum the number associated with the peer - * @return true if it was loaded correctly, false if there were errors - */ - public boolean load(Properties clientConfig, int peerNum) { - if ((clientConfig == null) || (peerNum < 0)) return false; - String peerVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_PEER); - String statFileVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_STATFILE); - String statDurationVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_STATDURATION); - String statFrequencyVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_STATFREQUENCY); - String sendFrequencyVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_SENDFREQUENCY); - String sendSizeVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_SENDSIZE); - String commentVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_COMMENT); - String periodsVal = clientConfig.getProperty(PROP_PREFIX + peerNum + PROP_AVERAGEPERIODS); - - if ((peerVal == null) || (statFileVal == null) || (statDurationVal == null) || (statFrequencyVal == null) - || (sendFrequencyVal == null) || (sendSizeVal == null)) { - if (_log.shouldLog(Log.DEBUG)) { - _log.debug("Peer number " + peerNum + " does not exist"); - } - return false; - } - - try { - int duration = getInt(statDurationVal); - int statFreq = getInt(statFrequencyVal); - int sendFreq = getInt(sendFrequencyVal); - int sendSize = getInt(sendSizeVal); - - if ((duration <= 0) || (statFreq <= 0) || (sendFreq < 0) || (sendSize <= 0)) { - if (_log.shouldLog(Log.WARN)) { - _log.warn("Invalid client config: duration [" + statDurationVal + "] stat frequency [" - + statFrequencyVal + "] send frequency [" + sendFrequencyVal + "] send size [" - + sendSizeVal + "]"); - } - return false; - } - - statFileVal = statFileVal.trim(); - if (statFileVal.length() <= 0) { - if (_log.shouldLog(Log.WARN)) { - _log.warn("Stat file is blank for peer " + peerNum); - } - return false; - } - - Destination d = new Destination(); - d.fromBase64(peerVal); - - if (commentVal == null) { - commentVal = ""; - } - - commentVal = commentVal.trim(); - commentVal = commentVal.replace('\n', '_'); - - List periods = new ArrayList(4); - if (periodsVal != null) { - StringTokenizer tok = new StringTokenizer(periodsVal); - while (tok.hasMoreTokens()) { - String periodVal = tok.nextToken(); - int minutes = getInt(periodVal); - if (minutes > 0) { - periods.add(new Integer(minutes)); - } - } - } - int avgPeriods[] = new int[periods.size()]; - for (int i = 0; i < periods.size(); i++) { - avgPeriods[i] = ((Integer) periods.get(i)).intValue(); - } - - _comment = commentVal; - _statDuration = duration; - _statFrequency = statFreq; - _sendFrequency = sendFreq; - _sendSize = sendSize; - _statFile = statFileVal; - _peer = d; - _averagePeriods = avgPeriods; - return true; - } catch (DataFormatException dfe) { - _log.error("Peer destination for " + peerNum + " was invalid: " + peerVal); - return false; - } - } - - /** - * Store the client config to the properties specified, deriving the current config entry from the peer number. - * - * @param clientConfig the properties to store to - * @param peerNum the number associated with the peer - * @return true if it was stored correctly, false if there were errors - */ - public boolean store(Properties clientConfig, int peerNum) { - if ((_peer == null) || (_sendFrequency < 0) || (_sendSize <= 0) || (_statDuration <= 0) - || (_statFrequency <= 0) || (_statFile == null)) { return false; } - - String comment = _comment; - if (comment == null) { - comment = ""; - } - - comment = comment.trim(); - comment = comment.replace('\n', '_'); - - StringBuffer buf = new StringBuffer(32); - if (_averagePeriods != null) { - for (int i = 0; i < _averagePeriods.length; i++) { - buf.append(_averagePeriods[i]).append(' '); - } - } - - clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_PEER, _peer.toBase64()); - clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_STATFILE, _statFile); - clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_STATDURATION, _statDuration + ""); - clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_STATFREQUENCY, _statFrequency + ""); - clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_SENDFREQUENCY, _sendFrequency + ""); - clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_SENDSIZE, _sendSize + ""); - clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_COMMENT, comment); - clientConfig.setProperty(PROP_PREFIX + peerNum + PROP_AVERAGEPERIODS, buf.toString()); - return true; - } - - private static final int getInt(String val) { - if (val == null) return -1; - try { - int i = Integer.parseInt(val); - return i; - } catch (NumberFormatException nfe) { - if (_log.shouldLog(Log.DEBUG)) { - _log.debug("Value [" + val + "] is not a valid integer"); - } - return -1; - } - } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/ClientEngine.java b/apps/heartbeat/java/src/net/i2p/heartbeat/ClientEngine.java deleted file mode 100644 index 15230f40a..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/ClientEngine.java +++ /dev/null @@ -1,133 +0,0 @@ -package net.i2p.heartbeat; - -import net.i2p.data.Destination; -import net.i2p.util.Clock; -import net.i2p.util.I2PThread; -import net.i2p.util.Log; - -/** - * Responsible for actually conducting the tests, coordinating the storing of the - * stats, and the management of the rates. This has its own thread specific for - * pumping data around as well. - * - */ -class ClientEngine { - private static final Log _log = new Log(ClientEngine.class); - /** who can send our pings? */ - private Heartbeat _heartbeat; - /** actual test state */ - private PeerData _data; - /** have we been stopped? */ - private boolean _active; - /** used to generate engine IDs */ - private static int __id = 0; - /** this engine's id, unique to the {test,sendingClient,startTime} */ - private int _id; - private static PeerDataWriter writer = new PeerDataWriter(); - - /** - * Create a new engine that will send its pings through the given heartbeat - * system, and will coordinate the test according to the configuration specified. - * @param heartbeat the Heartbeat to send pings through - * @param config the Configuration to load configuration from =p - */ - public ClientEngine(Heartbeat heartbeat, ClientConfig config) { - _heartbeat = heartbeat; - _data = new PeerData(config); - _active = false; - _id = ++__id; - } - - /** stop sending any more pings or writing any more state */ - public void stopEngine() { - _active = false; - if (_log.shouldLog(Log.INFO)) - _log.info("Stopping engine talking to peer " + _data.getConfig().getPeer().calculateHash().toBase64()); - } - - /** start up the test (this does not block, as it fires up the test thread) */ - public void startEngine() { - _active = true; - I2PThread t = new I2PThread(new ClientRunner()); - t.setName("HeartbeatClient " + _id); - t.start(); - } - - /** - * Who are we testing? - * @return the Destination (peer) we're testing - */ - public Destination getPeer() { - return _data.getConfig().getPeer(); - } - - /** - * What is our series identifier (used to locally identify a test) - * @return the series identifier - */ - public int getSeriesNum() { - return _id; - } - - /** - * receive notification from the heartbeat system that a pong was received in - * reply to a ping we have sent. - * - * @param sentOn when did we send the ping? - * @param replyOn when did the peer send the pong? - */ - public void receivePong(long sentOn, long replyOn) { - _data.pongReceived(sentOn, replyOn); - } - - /** fire off a new ping */ - private void doSend() { - long now = Clock.getInstance().now(); - _data.addPing(now); - _heartbeat.sendPing(_data.getConfig().getPeer(), _id, now, _data.getConfig().getSendSize()); - } - - /** our actual heartbeat pumper - this drives the test */ - private class ClientRunner implements Runnable { - - /** - * @see java.lang.Runnable#run() - */ - public void run() { - if (_log.shouldLog(Log.INFO)) - _log.info("Starting engine talking to peer " + _data.getConfig().getPeer().calculateHash().toBase64()); - - // when do we need to send the next PING? - long nextSend = Clock.getInstance().now(); - // when do we need to write out the next state data? - long nextWrite = Clock.getInstance().now(); - - while (_active) { - - if (Clock.getInstance().now() >= nextSend) { - doSend(); - nextSend = Clock.getInstance().now() + _data.getConfig().getSendFrequency() * 1000; - } - - if (Clock.getInstance().now() >= nextWrite) { - boolean written = writer.persist(_data); - if (!written) { - if (_log.shouldLog(Log.ERROR)) _log.error("Unable to write the client state data"); - } else { - if (_log.shouldLog(Log.DEBUG)) _log.debug("Client state data written"); - } - } - - _data.cleanup(); - - long timeToWait = nextSend - Clock.getInstance().now(); - if (timeToWait > 0) { - try { - Thread.sleep(timeToWait); - } catch (InterruptedException ie) { - } - } - } - } - } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/Heartbeat.java b/apps/heartbeat/java/src/net/i2p/heartbeat/Heartbeat.java deleted file mode 100644 index c577945f6..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/Heartbeat.java +++ /dev/null @@ -1,254 +0,0 @@ -package net.i2p.heartbeat; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; - -import net.i2p.data.Destination; -import net.i2p.util.Log; - -/** - * Main driver for the heartbeat engine, loading 0 or more tests, firing - * up a ClientEngine for each, and serving as a pong server. If there isn't - * a configuration file, or if the configuration file doesn't specify any tests, - * it simply sits around as a pong server, passively responding to whatever is - * sent its way.

- * - * The config file format is examplified below: - *

- *    # where the router is located (default is localhost)
- *    i2cpHost=localhost
- *    # I2CP port for the router (default is 7654)
- *    i2cpPort=4001
- *    # How many hops we want the router to put in our tunnels (default is 2)
- *    numHops=2
- *    # where our private destination keys are located - if this doesn't exist,
- *    # a new one will be created and saved there (by default, heartbeat.keys)
- *    privateDestinationFile=heartbeat_r2.keys
- *    # where do we want to export the plain base64 of our destination?
- *    publicDestinationFile=heartbeat_r2.txt
- *
- *    ## peer tests configured below:
- *    
- *    # destination peer for test 0
- *    peer.0.peer=[destination in base64]
- *    # where will we write out the stat data?
- *    peer.0.statFile=heartbeatStat_khWY_30s_1kb.txt
- *    # how many minutes will we keep stats for?
- *    peer.0.statDuration=30
- *    # how often will we write out new stat data (in seconds)?
- *    peer.0.statFrequency=60
- *    # how often will we send a ping to the peer (in seconds)?
- *    peer.0.sendFrequency=30
- *    # how many bytes will be included in the ping?
- *    peer.0.sendSize=1024
- *    # take a guess...
- *    peer.0.comment=Test with localhost sending 1KB of data every 30 seconds
- *    # we can keep track of a few moving averages - this value includes a whitespace
- *    # delimited list of numbers, each specifying a period to calculate the average
- *    # over (in minutes)
- *    peer.0.averagePeriods=1 5 30
- *    ## repeat the peer.0.* for as many tests as desired, incrementing as necessary
- * 
- * - */ -public class Heartbeat { - private static final Log _log = new Log(Heartbeat.class); - /** location containing this heartbeat's config */ - private String _configFile; - /** clientNum (Integer) to ClientConfig mapping */ - private Map _clientConfigs; - /** series num (Integer) to ClientEngine mapping */ - private Map _clientEngines; - /** helper class for managing our I2P send/receive and message formatting */ - private I2PAdapter _adapter; - /** our own callback that the I2PAdapter notifies on ping or pong messages */ - private PingPongAdapter _eventAdapter; - - /** if there are no command line arguments, load the config from "heartbeat.config" */ - public static final String CONFIG_FILE_DEFAULT = "heartbeat.config"; - - /** - * build up a new heartbeat manager, but don't actually do anything - * @param configFile the name of the configuration file - */ - public Heartbeat(String configFile) { - _configFile = configFile; - _clientConfigs = new HashMap(); - _clientEngines = new HashMap(); - _eventAdapter = new PingPongAdapter(); - _adapter = new I2PAdapter(); - _adapter.setListener(_eventAdapter); - } - - private Heartbeat() { - } - - /** load up the config data (but don't build any engines or start them up) */ - public void loadConfig() { - Properties props = new Properties(); - FileInputStream fin = null; - File configFile = new File(_configFile); - if (configFile.exists()) { - try { - fin = new FileInputStream(_configFile); - props.load(fin); - } catch (IOException ioe) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error reading the config data", ioe); - } - } finally { - if (fin != null) try { - fin.close(); - } catch (IOException ioe) { - } - } - } - - loadBaseConfig(props); - loadClientConfigs(props); - } - - /** - * send a ping message to the peer - * - * @param peer peer to ping - * @param seriesNum id used to keep track of multiple pings (of different size/frequency) to a peer - * @param now current time to be sent in the ping (so we can watch for it in the pong) - * @param size total message size to send - */ - void sendPing(Destination peer, int seriesNum, long now, int size) { - if (_adapter.getIsConnected()) _adapter.sendPing(peer, seriesNum, now, size); - } - - /** - * load up the base data (I2CP config, etc) - * @param props the properties to load from - */ - private void loadBaseConfig(Properties props) { - _adapter.loadConfig(props); - } - - /** - * load up all of the test config data - * @param props the properties to load from - * */ - private void loadClientConfigs(Properties props) { - int i = 0; - while (true) { - ClientConfig config = new ClientConfig(); - if (!config.load(props, i)) { - break; - } - _clientConfigs.put(new Integer(i), config); - i++; - } - } - - /** connect to the network */ - private void connect() { - boolean connected = _adapter.connect(); - if (!connected) _log.error("Unable to connect to the router"); - } - - /** disconnect from the network */ - private void disconnect() { /* UNUSED */ - _adapter.disconnect(); - } - - /** start up all of the tests */ - public void startEngines() { - for (Iterator iter = _clientConfigs.values().iterator(); iter.hasNext();) { - ClientConfig config = (ClientConfig) iter.next(); - ClientEngine engine = new ClientEngine(this, config); - config.setUs(_adapter.getLocalDestination()); - config.setNumHops(_adapter.getNumHops()); - _clientEngines.put(new Integer(engine.getSeriesNum()), engine); - engine.startEngine(); - } - } - - /** stop all of the tests */ - public void stopEngines() { - for (Iterator iter = _clientEngines.values().iterator(); iter.hasNext();) { - ClientEngine engine = (ClientEngine) iter.next(); - engine.stopEngine(); - } - _clientEngines.clear(); - } - - /** - * Fire up a new heartbeat system, waiting until, well, forever. Builds - * a new heartbeat system, loads the config, connects to the network, starts - * the engines, and then sits back and relaxes, responding to any pings and - * running any tests.

- * - * Usage: Heartbeat [configFileName]

- * @param args the list of args passed to the program from the command-line - */ - public static void main(String args[]) { - String configFile = CONFIG_FILE_DEFAULT; - if (args.length == 1) { - configFile = args[0]; - } - - if (_log.shouldLog(Log.INFO)) { - _log.info("Starting up with config file " + configFile); - } - Heartbeat heartbeat = new Heartbeat(configFile); - heartbeat.loadConfig(); - heartbeat.connect(); - heartbeat.startEngines(); - Object o = new Object(); - while (true) { - try { - synchronized (o) { - o.wait(); - } - } catch (InterruptedException ie) { - } - } - } - - /** - * Receive event notification from the I2PAdapter - * - */ - private class PingPongAdapter implements I2PAdapter.PingPongEventListener { - /** - * We were pinged, so always just send a pong back. - * - * @param from who sent us the ping? - * @param seriesNum what series did the sender specify? - * @param sentOn when did the sender say they sent their ping? - * @param data arbitrary payload data - */ - public void receivePing(Destination from, int seriesNum, Date sentOn, byte[] data) { - if (_adapter.getIsConnected()) { - _adapter.sendPong(from, seriesNum, sentOn, data); - } - } - - /** - * We received a pong, so find the right client engine and tell it about the pong. - * - * @param from who sent us the pong - * @param seriesNum our client ID - * @param sentOn when did we send the ping? - * @param replyOn when did they send their pong? - * @param data the arbitrary data we sent in the ping (that they sent back in the pong) - */ - public void receivePong(Destination from, int seriesNum, Date sentOn, Date replyOn, byte[] data) { - ClientEngine engine = (ClientEngine) _clientEngines.get(new Integer(seriesNum)); - if (engine.getPeer().equals(from)) { - engine.receivePong(sentOn.getTime(), replyOn.getTime()); - } - } - } - -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/I2PAdapter.java b/apps/heartbeat/java/src/net/i2p/heartbeat/I2PAdapter.java deleted file mode 100644 index 35c157c7b..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/I2PAdapter.java +++ /dev/null @@ -1,604 +0,0 @@ -package net.i2p.heartbeat; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Date; -import java.util.Properties; - -import net.i2p.I2PAppContext; -import net.i2p.I2PException; -import net.i2p.client.I2PClient; -import net.i2p.client.I2PClientFactory; -import net.i2p.client.I2PSession; -import net.i2p.client.I2PSessionException; -import net.i2p.client.I2PSessionListener; -import net.i2p.data.DataFormatException; -import net.i2p.data.DataHelper; -import net.i2p.data.Destination; -import net.i2p.util.Clock; -import net.i2p.util.Log; - -/** - * Tie-in to the I2P SDK for the Heartbeat system, talking to the I2PSession and - * dealing with the raw ping and pong messages. - * - */ -class I2PAdapter { - private final static Log _log = new Log(I2PAdapter.class); - /** I2CP host */ - private String _i2cpHost; - /** I2CP port */ - private int _i2cpPort; - /** how long do we want our tunnels to be? */ - private int _numHops; - /** filename containing the heartbeat engine's private destination info */ - private String _privateDestFile; - /** filename to store the heartbeat engine's public destination in base64*/ - private String _publicDestFile; - /** our destination */ - private Destination _localDest; - /** who do we tell? */ - private PingPongEventListener _listener; - /** how do we talk to the router */ - private I2PSession _session; - /** object that receives our i2cp notifications from the session and tells us */ - private I2PListener _i2pListener; /* UNUSED */ - - /** - * This config property tells us where the private destination data for our - * connection (or if it doesn't exist, where will we save it) - */ - private static final String DEST_FILE_PROP = "privateDestinationFile"; - /** by default, the private destination data is in "heartbeat.keys" */ - private static final String DEST_FILE_DEFAULT = "heartbeat.keys"; - /** where will we export the public destination in base 64? */ - private static final String PUBLIC_DEST_FILE_PROP = "publicDestinationFile"; - /** where will we export the public destination in base 64? */ - private static final String PUBLIC_DEST_FILE_DEFAULT = "heartbeat.txt"; - /** This config property defines where the I2P router is */ - private static final String I2CP_HOST_PROP = "i2cpHost"; - /** by default, the I2P host is "localhost" */ - private static final String I2CP_HOST_DEFAULT = "localhost"; - /** This config property defines the I2CP port on the router */ - private static final String I2CP_PORT_PROP = "i2cpPort"; - /** by default, the I2CP port is 7654 */ - private static final int I2CP_PORT_DEFAULT = 7654; - - /** This property defines how many hops we want in our tunnels. */ - public static final String NUMHOPS_PROP = "numHops"; - /** by default, use 2 hop tunnels */ - public static final int NUMHOPS_DEFAULT = 2; - - /** - * Constructs an I2PAdapter . . . - */ - public I2PAdapter() { - _privateDestFile = null; - _publicDestFile = null; - _i2cpHost = null; - _i2cpPort = -1; - _localDest = null; - _listener = null; - _session = null; - _numHops = 0; - } - - /** - * who are we? - * @return the destination (us) - */ - public Destination getLocalDestination() { - return _localDest; - } - - /** - * who gets notified when we receive a ping or a pong? - * @return the event listener who gets notified - */ - public PingPongEventListener getListener() { - return _listener; - } - - /** - * Sets who gets notified when we receive a ping or a pong - * @param listener the event listener to get notified - */ - public void setListener(PingPongEventListener listener) { - _listener = listener; - } - - /** - * how many hops do we want in our tunnels? - * @return the number of hops - */ - public int getNumHops() { - return _numHops; - } - - /** - * are we connected? - * @return true or false . . . - */ - public boolean getIsConnected() { - return _session != null; - } - - /** - * Read in all of the config data - * @param props the properties to load from - */ - void loadConfig(Properties props) { - String privDestFile = props.getProperty(DEST_FILE_PROP, DEST_FILE_DEFAULT); - String pubDestFile = props.getProperty(PUBLIC_DEST_FILE_PROP, PUBLIC_DEST_FILE_DEFAULT); - String host = props.getProperty(I2CP_HOST_PROP, I2CP_HOST_DEFAULT); - String port = props.getProperty(I2CP_PORT_PROP, "" + I2CP_PORT_DEFAULT); - String numHops = props.getProperty(NUMHOPS_PROP, "" + NUMHOPS_DEFAULT); - - int portNum = -1; - try { - portNum = Integer.parseInt(port); - } catch (NumberFormatException nfe) { - if (_log.shouldLog(Log.WARN)) { - _log.warn("Invalid I2CP port specified [" + port + "]"); - } - portNum = I2CP_PORT_DEFAULT; - } - int hops = -1; - try { - hops = Integer.parseInt(numHops); - } catch (NumberFormatException nfe) { - if (_log.shouldLog(Log.WARN)) { - _log.warn("Invalid # hops specified [" + numHops + "]"); - } - hops = NUMHOPS_DEFAULT; - } - - _numHops = hops; - _privateDestFile = privDestFile; - _publicDestFile = pubDestFile; - _i2cpHost = host; - _i2cpPort = portNum; - } - - /** - * write out the config to the props - * @param props the properties to write to - */ - void storeConfig(Properties props) { - if (_privateDestFile != null) { - props.setProperty(DEST_FILE_PROP, _privateDestFile); - } else { - props.setProperty(DEST_FILE_PROP, DEST_FILE_DEFAULT); - } - - if (_publicDestFile != null) { - props.setProperty(PUBLIC_DEST_FILE_PROP, _publicDestFile); - } else { - props.setProperty(PUBLIC_DEST_FILE_PROP, PUBLIC_DEST_FILE_DEFAULT); - } - - if (_i2cpHost != null) { - props.setProperty(I2CP_HOST_PROP, _i2cpHost); - } else { - props.setProperty(I2CP_HOST_PROP, I2CP_HOST_DEFAULT); - } - - if (_i2cpPort > 0) { - props.setProperty(I2CP_PORT_PROP, "" + _i2cpPort); - } else { - props.setProperty(I2CP_PORT_PROP, "" + I2CP_PORT_DEFAULT); - } - - props.setProperty(NUMHOPS_PROP, "" + _numHops); - } - - private static final int TYPE_PING = 0; - private static final int TYPE_PONG = 1; - - /** - * send a ping message to the peer - * - * @param peer peer to ping - * @param seriesNum id used to keep track of multiple pings (of different size/frequency) to a peer - * @param now current time to be sent in the ping (so we can watch for it in the pong) - * @param size total message size to send - * - * @throws IllegalStateException if we are not connected to the router - */ - public void sendPing(Destination peer, int seriesNum, long now, int size) { - if (_session == null) throw new IllegalStateException("Not connected to the router"); - ByteArrayOutputStream baos = new ByteArrayOutputStream(size); - try { - _localDest.writeBytes(baos); - DataHelper.writeLong(baos, 2, seriesNum); - DataHelper.writeLong(baos, 1, TYPE_PING); - DataHelper.writeDate(baos, new Date(now)); - int padding = size - baos.size(); - byte paddingData[] = new byte[padding]; - I2PAppContext.getGlobalContext().random().nextBytes(paddingData); - //Arrays.fill(paddingData, (byte) 0x2A); - DataHelper.writeLong(baos, 2, padding); - baos.write(paddingData); - boolean sent = _session.sendMessage(peer, baos.toByteArray()); - if (!sent) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error sending the ping to " + peer.calculateHash().toBase64() + " for series " - + seriesNum); - } - } else { - if (_log.shouldLog(Log.INFO)) { - _log.info("Ping sent to " + peer.calculateHash().toBase64() + " for series " + seriesNum); - } - } - } catch (IOException ioe) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error sending the ping", ioe); - } - } catch (DataFormatException dfe) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error writing out the ping message", dfe); - } - } catch (I2PSessionException ise) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error writing out the ping message", ise); - } - } - } - - /** - * send a pong message to the peer - * - * @param peer peer to pong - * @param seriesNum id given to us in the ping - * @param sentOn date the peer said they sent us the message - * @param data payload the peer sent us in the ping - * - * @throws IllegalStateException if we are not connected to the router - */ - public void sendPong(Destination peer, int seriesNum, Date sentOn, byte data[]) { - if (_session == null) throw new IllegalStateException("Not connected to the router"); - ByteArrayOutputStream baos = new ByteArrayOutputStream(data.length + 768); - try { - _localDest.writeBytes(baos); - DataHelper.writeLong(baos, 2, seriesNum); - DataHelper.writeLong(baos, 1, TYPE_PONG); - DataHelper.writeDate(baos, sentOn); - DataHelper.writeDate(baos, new Date(Clock.getInstance().now())); - DataHelper.writeLong(baos, 2, data.length); - baos.write(data); - boolean sent = _session.sendMessage(peer, baos.toByteArray()); - if (!sent) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error sending the pong to " + peer.calculateHash().toBase64() + " for series " - + seriesNum + " which was sent on " + sentOn); - } - } else { - if (_log.shouldLog(Log.INFO)) { - _log.info("Pong sent to " + peer.calculateHash().toBase64() + " for series " + seriesNum - + " which was sent on " + sentOn); - } - } - } catch (IOException ioe) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error sending the ping", ioe); - } - } catch (DataFormatException dfe) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error writing out the pong message", dfe); - } - } catch (I2PSessionException ise) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error writing out the pong message", ise); - } - } - } - - /** - * We've received this data from I2P - parse it into a ping or a pong - * and notify accordingly - * @param data the data to handle - */ - private void handleMessage(byte data[]) { - ByteArrayInputStream bais = new ByteArrayInputStream(data); - try { - Destination from = new Destination(); - from.readBytes(bais); - int series = (int) DataHelper.readLong(bais, 2); - long type = DataHelper.readLong(bais, 1); - Date sentOn = DataHelper.readDate(bais); - Date receivedOn = null; - if (type == TYPE_PONG) { - receivedOn = DataHelper.readDate(bais); - } - int size = (int) DataHelper.readLong(bais, 2); - byte payload[] = new byte[size]; - int read = DataHelper.read(bais, payload); - if (read != size) { throw new IOException("Malformed payload - read " + read + " instead of " + size); } - - if (_listener == null) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Listener isn't set, but we received a valid message of type " + type + " sent from " - + from.calculateHash().toBase64()); - } - return; - } - - if (type == TYPE_PING) { - if (_log.shouldLog(Log.INFO)) { - _log.info("Ping received from " + from.calculateHash().toBase64() + " on series " + series - + " sent on " + sentOn + " containing " + size + " bytes"); - } - _listener.receivePing(from, series, sentOn, payload); - } else if (type == TYPE_PONG) { - if (_log.shouldLog(Log.INFO)) { - _log.info("Pong received from " + from.calculateHash().toBase64() + " on series " + series - + " sent on " + sentOn + " with pong sent on " + receivedOn + " containing " + size - + " bytes"); - } - _listener.receivePong(from, series, sentOn, receivedOn, payload); - } else { - throw new IOException("Invalid message type " + type); - } - - } catch (IOException ioe) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error handling the message", ioe); - } - } catch (DataFormatException dfe) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error parsing the message", dfe); - } - } - } - - /** - * connect to the I2P router and either authenticate ourselves with the - * destination we're given, or create a new one and write that to the - * destination file. - * - * @return true if we connect successfully, false otherwise - */ - boolean connect() { - I2PClient client = I2PClientFactory.createClient(); - Destination us = null; - File destFile = new File(_privateDestFile); - us = verifyDestination(client, destFile); - if (us == null) return false; - - // if we're here, we got a destination. lets connect - FileInputStream fin = null; - try { - fin = new FileInputStream(destFile); - Properties options = getOptions(); - I2PSession session = client.createSession(fin, options); - I2PListener lsnr = new I2PListener(); - session.setSessionListener(lsnr); - session.connect(); - _localDest = session.getMyDestination(); - if (_log.shouldLog(Log.INFO)) { - _log.info("I2CP Session created and connected as " + _localDest.calculateHash().toBase64()); - } - _session = session; - _i2pListener = lsnr; - } catch (I2PSessionException ise) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error connecting", ise); - } - return false; - } catch (IOException ioe) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error loading the destionation", ioe); - } - return false; - } finally { - if (fin != null) try { - fin.close(); - } catch (IOException ioe) { - } - } - - return true; - } - - /** - * load, verify, or create a destination - * - * @param client the client - * @param destFile the file holding the destination - * @return the destination loaded, or null if there was an error - */ - private Destination verifyDestination(I2PClient client, File destFile) { - Destination us = null; - FileInputStream fin = null; - if (destFile.exists()) { - try { - fin = new FileInputStream(destFile); - us = new Destination(); - us.readBytes(fin); - if (_log.shouldLog(Log.INFO)) { - _log.info("Existing destination loaded: [" + us.toBase64() + "]"); - } - - FileOutputStream fos = null; - try { - fos = new FileOutputStream(_publicDestFile); - fos.write(us.toBase64().getBytes()); - fos.flush(); - } catch (IOException fioe) { - _log.error("Error writing out the plain destination to [" + _publicDestFile + "]", fioe); - } finally { - if (fos != null) try { fos.close(); } catch (IOException fioe) {} - } - - } catch (IOException ioe) { - if (fin != null) try { - fin.close(); - } catch (IOException ioe2) { - } - fin = null; - destFile.delete(); - us = null; - } catch (DataFormatException dfe) { - if (fin != null) try { - fin.close(); - } catch (IOException ioe2) { - } - fin = null; - destFile.delete(); - us = null; - } finally { - if (fin != null) try { - fin.close(); - } catch (IOException ioe2) { - } - fin = null; - } - } - - if (us == null) { - // need to create a new one - FileOutputStream fos = null; - try { - fos = new FileOutputStream(destFile); - us = client.createDestination(fos); - if (_log.shouldLog(Log.INFO)) { - _log.info("New destination created: [" + us.toBase64() + "]"); - } - fos.close(); - - try { - fos = new FileOutputStream(_publicDestFile); - fos.write(us.toBase64().getBytes()); - fos.flush(); - } catch (IOException fioe) { - _log.error("Error writing out the plain destination to [" + _publicDestFile + "]", fioe); - } finally { - if (fos != null) try { fos.close(); } catch (IOException fioe) {} - fos = null; - } - - } catch (IOException ioe) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error writing out the destination keys being created", ioe); - } - return null; - } catch (I2PException ie) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error creating the destination", ie); - } - return null; - } finally { - if (fos != null) try { - fos.close(); - } catch (IOException ioe) { - } - } - } - return us; - } - - /** - * I2PSession connect options - * @return the options as Properties - */ - private Properties getOptions() { - Properties props = new Properties(); - // this should be BEST_EFFORT, but i'm too lazy to update the code to handle tracking - // sessionTags and sessionKeys, marking them as delivered on pong. - props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_GUARANTEED); - props.setProperty(I2PClient.PROP_TCP_HOST, _i2cpHost); - props.setProperty(I2PClient.PROP_TCP_PORT, _i2cpPort + ""); - props.setProperty("tunnels.depthInbound", "" + _numHops); - props.setProperty("tunnels.depthOutbound", "" + _numHops); - return props; - } - - /** disconnect from the I2P router */ - void disconnect() { - if (_session != null) { - try { - _session.destroySession(); - } catch (I2PSessionException ise) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Error destroying the session", ise); - } - } - _session = null; - } - } - - /** - * Defines an event notification system for receiving pings and pongs - * - */ - public interface PingPongEventListener { - /** - * receive a ping message from the peer - * - * @param from peer that sent us the ping - * @param seriesNum id the peer sent us in the ping - * @param sentOn date the peer said they sent us the message - * @param data payload from the ping - */ - void receivePing(Destination from, int seriesNum, Date sentOn, byte data[]); - - /** - * receive a pong message from the peer - * - * @param from peer that sent us the pong - * @param seriesNum id the peer sent us in the pong (that we sent them in the ping) - * @param sentOn when we sent out the ping - * @param replyOn when they sent out the pong - * @param data payload from the ping/pong - */ - void receivePong(Destination from, int seriesNum, Date sentOn, Date replyOn, byte data[]); - } - - /** - * Receive data from the session and pass it along to handleMessage for parsing/dispersal - * - */ - private class I2PListener implements I2PSessionListener { - - /* (non-Javadoc) - * @see net.i2p.client.I2PSessionListener#disconnected(net.i2p.client.I2PSession) - */ - public void disconnected(I2PSession session) { - if (_log.shouldLog(Log.ERROR)) { - _log.error("Session disconnected"); - } - disconnect(); - } - - /* (non-Javadoc) - * @see net.i2p.client.I2PSessionListener#errorOccurred(net.i2p.client.I2PSession, java.lang.String, java.lang.Throwable) - */ - public void errorOccurred(I2PSession session, String message, Throwable error) { - if (_log.shouldLog(Log.ERROR)) _log.error("Error occurred: " + message, error); - } - - /* (non-Javadoc) - * @see net.i2p.client.I2PSessionListener#reportAbuse(net.i2p.client.I2PSession, int) - */ - public void reportAbuse(I2PSession session, int severity) { - if (_log.shouldLog(Log.ERROR)) _log.error("Abuse reported with severity " + String.valueOf(severity)); - } - - /* (non-Javadoc) - * @see net.i2p.client.I2PSessionListener#messageAvailable(net.i2p.client.I2PSession, int, long) - */ - public void messageAvailable(I2PSession session, int msgId, long size) { - try { - byte data[] = session.receiveMessage(msgId); - handleMessage(data); - } catch (I2PSessionException ise) { - if (_log.shouldLog(Log.ERROR)) _log.error("Error receiving the message", ise); - disconnect(); - } - } - } -} diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/PeerData.java b/apps/heartbeat/java/src/net/i2p/heartbeat/PeerData.java deleted file mode 100644 index 6d9e93fb3..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/PeerData.java +++ /dev/null @@ -1,412 +0,0 @@ -package net.i2p.heartbeat; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -import net.i2p.stat.Rate; -import net.i2p.stat.RateStat; -import net.i2p.util.Clock; -import net.i2p.util.Log; - -/** - * Contain the current window of data for a particular series of ping/pong stats - * sent to a peer. This should be periodically kept clean by calling cleanup() - * to timeout expired pings and to drop data outside the window. - * - */ -public class PeerData { - private final static Log _log = new Log(PeerData.class); - /** peer / sequence / config in this data series */ - private ClientConfig _peer; - /** date sent (Long) to EventDataPoint containing the datapoints sent in the current period */ - private Map _dataPoints; - /** date sent (Long) to EventDataPoint containing pings that haven't yet timed out or been ponged */ - private TreeMap _pendingPings; - private long _sessionStart; - private long _lifetimeSent; - private long _lifetimeReceived; - /** rate averaging the time to send over a variety of periods */ - private RateStat _sendRate; - /** rate averaging the time to receive over a variety of periods */ - private RateStat _receiveRate; - /** rate averaging the frequency of lost messages over a variety of periods */ - private RateStat _lostRate; - - /** how long we wait before timing out pending pings (30 seconds) */ - private static final long TIMEOUT_PERIOD = 60 * 1000; - - /** synchronize on this when updating _dataPoints or _pendingPings */ - private Object _updateLock = new Object(); - - /** - * Creates a PeerData . . . - * @param config configuration to load from - */ - public PeerData(ClientConfig config) { - _peer = config; - _dataPoints = new TreeMap(); - _pendingPings = new TreeMap(); - _sessionStart = Clock.getInstance().now(); - _lifetimeSent = 0; - _lifetimeReceived = 0; - _sendRate = new RateStat("sendRate", "How long it takes to send", "peer", - getPeriods(config.getAveragePeriods())); - _receiveRate = new RateStat("receiveRate", "How long it takes to receive", "peer", - getPeriods(config.getAveragePeriods())); - _lostRate = new RateStat("lostRate", "How frequently we lose messages", "peer", - getPeriods(config.getAveragePeriods())); - } - - /** - * turn the periods (# minutes) into rate periods (# milliseconds) - * @param periods (in minutes) - * @return an array of periods (in milliseconds) - */ - private static long[] getPeriods(int periods[]) { - long rv[] = null; - if (periods == null) periods = new int[0]; - rv = new long[periods.length]; - for (int i = 0; i < periods.length; i++) - rv[i] = (long) periods[i] * 60 * 1000; // they're in minutes - Arrays.sort(rv); - return rv; - } - - /** - * how many pings are still outstanding? - * @return the number of pings outstanding - */ - public int getPendingCount() { - synchronized (_updateLock) { - return _pendingPings.size(); - } - } - - /** - * how many data points are available in the current window? - * @return the number of datapoints available - */ - public int getDataPointCount() { - synchronized (_updateLock) { - return _dataPoints.size(); - } - } - - /** - * when did this test begin? - * @return when the test began - */ - public long getSessionStart() { return _sessionStart; } - - /** - * sets when the test began - * @param when when it began - */ - public void setSessionStart(long when) { _sessionStart = when; } - - /** - * how many pings have we sent for this test? - * @return the number of pings sent - */ - public long getLifetimeSent() { return _lifetimeSent; } - - /** - * how many pongs have we received for this test? - * @return the number of pings received - */ - public long getLifetimeReceived() { return _lifetimeReceived; } - - /** - * @return the client configuration - */ - public ClientConfig getConfig() { - return _peer; - } - - /** - * What periods are we averaging the data over (in minutes)? - * @return the periods as an array of ints (in minutes) - */ - public int[] getAveragePeriods() { - return (_peer.getAveragePeriods() != null ? _peer.getAveragePeriods() : new int[0]); - } - - /** - * average time to send over the given period. - * - * @param period number of minutes to retrieve the average for - * @return milliseconds average, or -1 if we dont track that period - */ - public double getAverageSendTime(int period) { - return getAverage(_sendRate, period); - } - - /** - * average time to receive over the given period. - * - * @param period number of minutes to retrieve the average for - * @return milliseconds average, or -1 if we dont track that period - */ - public double getAverageReceiveTime(int period) { - return getAverage(_receiveRate, period); - } - - /** - * number of lost messages over the given period. - * - * @param period number of minutes to retrieve the average for - * @return number of lost messages in the period, or -1 if we dont track that period - */ - public double getLostMessages(int period) { - Rate rate = _lostRate.getRate(period * 60 * 1000); - if (rate == null) return -1; - return rate.getCurrentTotalValue(); - } - - private double getAverage(RateStat stat, int period) { - Rate rate = stat.getRate(period * 60 * 1000); - if (rate == null) return -1; - return rate.getAverageValue(); - } - - /** - * Return an ordered list of data points in the current window (after doing a cleanup) - * - * @return list of EventDataPoint objects - */ - public List getDataPoints() { - cleanup(); - synchronized (_updateLock) { - return new ArrayList(_dataPoints.values()); - } - } - - /** - * We have sent the peer a ping on this series (using the send time as given) - * @param dateSent when the ping was sent - */ - public void addPing(long dateSent) { - EventDataPoint sent = new EventDataPoint(dateSent); - synchronized (_updateLock) { - _pendingPings.put(new Long(dateSent), sent); - } - _lifetimeSent++; - } - - /** - * we have received a pong from the peer on this series - * - * @param dateSent when we sent the ping - * @param pongSent when the peer received the ping and sent the pong - */ - public void pongReceived(long dateSent, long pongSent) { - long now = Clock.getInstance().now(); - synchronized (_updateLock) { - if (_pendingPings.size() <= 0) { - _log.warn("Pong received (sent at " + dateSent + ", " + (now-dateSent) - + "ms ago, pong delay " + (pongSent-dateSent) + "ms, pong receive delay " - + (now-pongSent) + "ms)"); - return; - } - Long first = (Long)_pendingPings.firstKey(); - EventDataPoint data = (EventDataPoint)_pendingPings.remove(new Long(dateSent)); - - if (data != null) { - data.setPongReceived(now); - data.setPongSent(pongSent); - data.setWasPonged(true); - locked_addDataPoint(data); - - if (dateSent != first.longValue()) { - _log.error("Out of order delivery: received " + dateSent - + " but the first pending is " + first.longValue() - + " (delta " + (dateSent - first.longValue()) + ")"); - } else { - _log.info("In order delivery for " + dateSent + " in ping " - + _peer.getComment()); - } - } else { - _log.warn("Pong received, but no matching ping? ping sent at = " + dateSent); - return; - } - } - _sendRate.addData(pongSent - dateSent, 0); - _receiveRate.addData(now - pongSent, 0); - _lifetimeReceived++; - } - - protected void addDataPoint(EventDataPoint data) { - synchronized (_updateLock) { - locked_addDataPoint(data); - } - } - - private void locked_addDataPoint(EventDataPoint data) { - Object val = _dataPoints.put(new Long(data.getPingSent()), data); - if (val != null) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Duplicate data point received: " + data); - } - } - - /** - * drop all datapoints outside the window we're watching, and timeout all - * pending pings not ponged in the TIMEOUT_PERIOD, both updating the lost message - * rate and coallescing all of the rates. - * - */ - public void cleanup() { - long dropBefore = Clock.getInstance().now() - _peer.getStatDuration() * 60 * 1000; - long timeoutBefore = Clock.getInstance().now() - TIMEOUT_PERIOD; - long numDropped = 0; - long numTimedOut = 0; - - synchronized (_updateLock) { - numDropped = locked_dropExpired(dropBefore); - numTimedOut = locked_timeoutPending(timeoutBefore); - } - - _lostRate.addData(numTimedOut, 0); - - _receiveRate.coalesceStats(); - _sendRate.coalesceStats(); - _lostRate.coalesceStats(); - - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Peer data cleaned up " + numTimedOut + " timed out pings and removed " + numDropped - + " old entries"); - } - - /** - * Drop all data points that are already too old for us to be interested in - * - * @param when the earliest ping send time we care about - * @return number of data points dropped - */ - private int locked_dropExpired(long when) { - Set toDrop = new HashSet(4); - // drop the failed and really old - for (Iterator iter = _dataPoints.keySet().iterator(); iter.hasNext(); ) { - Long pingTime = (Long)iter.next(); - if (pingTime.longValue() < when) - toDrop.add(pingTime); - } - for (Iterator iter = toDrop.iterator(); iter.hasNext(); ) { - _dataPoints.remove(iter.next()); - } - return toDrop.size(); - } - - /** - * timeout and remove all pings that were sent before the given time, - * moving them from the set of pending pings to the set of data points - * - * @param when the earliest ping send time we care about - * @return number of pings timed out - */ - private int locked_timeoutPending(long when) { - Set toDrop = new HashSet(4); - for (Iterator iter = _pendingPings.keySet().iterator(); iter.hasNext(); ) { - Long pingTime = (Long)iter.next(); - if (pingTime.longValue() < when) { - toDrop.add(pingTime); - EventDataPoint point = (EventDataPoint)_pendingPings.get(pingTime); - point.setWasPonged(false); - locked_addDataPoint(point); - } - } - for (Iterator iter = toDrop.iterator(); iter.hasNext(); ) { - _pendingPings.remove(iter.next()); - } - return toDrop.size(); - } - - /** actual data point for the peer */ - public class EventDataPoint { - private boolean _wasPonged; - private long _pingSent; - private long _pongSent; - private long _pongReceived; - - /** - * Creates an EventDataPoint - */ - public EventDataPoint() { this(-1); } - - /** - * Creates an EventDataPoint with pingtime associated with it =) - * @param pingSentOn the time a ping was sent - */ - public EventDataPoint(long pingSentOn) { - _wasPonged = false; - _pingSent = pingSentOn; - _pongSent = -1; - _pongReceived = -1; - } - - /** - * when did we send this ping? - * @return the time the ping was sent - */ - public long getPingSent() { return _pingSent; } - - /** - * sets when we sent this ping - * @param when when we sent the ping - */ - public void setPingSent(long when) { _pingSent = when; } - - /** - * when did the peer receive the ping? - * @return the time the ping was receieved - */ - public long getPongSent() { - return _pongSent; - } - - /** - * Set the time the peer received the ping - * @param when the time to set - */ - public void setPongSent(long when) { - _pongSent = when; - } - - /** - * when did we receive the peer's pong? - * @return the time we receieved the pong - */ - public long getPongReceived() { - return _pongReceived; - } - - /** - * Set the time the peer's pong was receieved - * @param when the time to set - */ - public void setPongReceived(long when) { - _pongReceived = when; - } - - /** - * did the peer reply in time? - * @return true or false, whether we got a reply in time */ - public boolean getWasPonged() { - return _wasPonged; - } - - /** - * Set whether we receieved the peer's reply in time - * @param pong true or false - */ - public void setWasPonged(boolean pong) { - _wasPonged = pong; - } - } -} diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/PeerDataWriter.java b/apps/heartbeat/java/src/net/i2p/heartbeat/PeerDataWriter.java deleted file mode 100644 index ad76fd1ce..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/PeerDataWriter.java +++ /dev/null @@ -1,142 +0,0 @@ -package net.i2p.heartbeat; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Iterator; -import java.util.Locale; - -import net.i2p.util.Clock; -import net.i2p.util.Log; - -/** - * Actually write out the stats for peer test - * - */ -public class PeerDataWriter { - private final static Log _log = new Log(PeerDataWriter.class); - - /** - * persist the peer state to the location specified in the peer config - * - * @param data the peer data to persist - * @return true if it was persisted correctly, false on error - */ - public boolean persist(PeerData data) { - String filename = data.getConfig().getStatFile(); - File statFile = new File(filename); - FileOutputStream fos = null; - try { - fos = new FileOutputStream(statFile); - persist(data, fos); - } catch (IOException ioe) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Error persisting the peer data for " - + data.getConfig().getPeer().calculateHash().toBase64(), ioe); - return false; - } finally { - if (fos != null) try { - fos.close(); - } catch (IOException ioe) { - } - } - return true; - } - - /** - * persists the peer state to the output stream - * @param data the peer data to persist - * @param out where to persist the data - * @return true if it was persisted correctly [always (as implemented)], false on error - * @throws IOException - */ - public boolean persist(PeerData data, OutputStream out) throws IOException { - String header = getHeader(data); - - out.write(header.getBytes()); - out.write("#action\tstatus\tdate and time sent \tsendMs\treplyMs\troundTrip\n".getBytes()); - for (Iterator iter = data.getDataPoints().iterator(); iter.hasNext();) { - PeerData.EventDataPoint point = (PeerData.EventDataPoint) iter.next(); - String line = getEvent(point); - out.write(line.getBytes()); - } - return true; - } - - private String getHeader(PeerData data) { - StringBuffer buf = new StringBuffer(1024); - buf.append("peer \t").append(data.getConfig().getPeer().calculateHash().toBase64()).append('\n'); - buf.append("local \t").append(data.getConfig().getUs().calculateHash().toBase64()).append('\n'); - buf.append("peerDest \t").append(data.getConfig().getPeer().toBase64()).append('\n'); - buf.append("localDest \t").append(data.getConfig().getUs().toBase64()).append('\n'); - buf.append("numTunnelHops\t").append(data.getConfig().getNumHops()).append('\n'); - buf.append("comment \t").append(data.getConfig().getComment()).append('\n'); - buf.append("sendFrequency\t").append(data.getConfig().getSendFrequency()).append('\n'); - buf.append("sendSize \t").append(data.getConfig().getSendSize()).append('\n'); - buf.append("sessionStart \t").append(getTime(data.getSessionStart())).append('\n'); - buf.append("currentTime \t").append(getTime(Clock.getInstance().now())).append('\n'); - buf.append("numPending \t").append(data.getPendingCount()).append('\n'); - buf.append("lifetimeSent \t").append(data.getLifetimeSent()).append('\n'); - buf.append("lifetimeRecv \t").append(data.getLifetimeReceived()).append('\n'); - int periods[] = data.getAveragePeriods(); - buf.append("#averages\tminutes\tsendMs\trecvMs\tnumLost\troundTrip\n"); - for (int i = 0; i < periods.length; i++) { - buf.append("periodAverage\t").append(periods[i]).append('\t'); - buf.append(getNum(data.getAverageSendTime(periods[i]))).append('\t'); - buf.append(getNum(data.getAverageReceiveTime(periods[i]))).append('\t'); - buf.append(getNum(data.getLostMessages(periods[i]))).append('\t'); - double rtt = data.getAverageSendTime(periods[i]) - + data.getAverageReceiveTime(periods[i]); - buf.append(getNum(rtt)).append('\n'); - } - return buf.toString(); - } - - private String getEvent(PeerData.EventDataPoint point) { - StringBuffer buf = new StringBuffer(128); - buf.append("EVENT\t"); - if (point.getWasPonged()) - buf.append("OK\t"); - else - buf.append("LOST\t"); - buf.append(getTime(point.getPingSent())).append('\t'); - if (point.getWasPonged()) { - buf.append(point.getPongSent() - point.getPingSent()).append('\t'); - buf.append(point.getPongReceived() - point.getPongSent()).append('\t'); - buf.append(point.getPongReceived() - point.getPingSent()).append('\t'); - } - buf.append('\n'); - return buf.toString(); - } - - private final SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd.HH:mm:ss.SSS", Locale.UK); - - /** - * Converts a time (long) to text - * @param when the time to convert - * @return the textual representation - */ - public String getTime(long when) { - synchronized (_fmt) { - return _fmt.format(new Date(when)); - } - } - - private final DecimalFormat _numFmt = new DecimalFormat("#0", new DecimalFormatSymbols(Locale.UK)); - - /** - * Converts a number (double) to text - * @param val the number to convert - * @return the textual representation - */ - public String getNum(double val) { - synchronized (_numFmt) { - return _numFmt.format(val); - } - } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatControlPane.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatControlPane.java deleted file mode 100644 index d28144731..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatControlPane.java +++ /dev/null @@ -1,108 +0,0 @@ -package net.i2p.heartbeat.gui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; - -import net.i2p.util.Log; - -/** - * Render the control widgets (refresh/load/snapshot and the - * tabbed panel with the plot config data) - * - */ -class HeartbeatControlPane extends JPanel { - private final static Log _log = new Log(HeartbeatControlPane.class); - private HeartbeatMonitorGUI _gui; - private JTabbedPane _configPane; - private final static Color WHITE = new Color(255, 255, 255); - private final static Color LIGHT_BLUE = new Color(180, 180, 255); /* UNUSED */ - private final static Color BLACK = new Color(0, 0, 0); - private Color _background = WHITE; - private Color _foreground = BLACK; - - /** - * Constructs a control panel onto the gui - * @param gui the gui the panel is associated with - */ - public HeartbeatControlPane(HeartbeatMonitorGUI gui) { - _gui = gui; - initializeComponents(); - } - - /** - * Adds a test to the panel - * @param config the configuration for the test - */ - public void addTest(PeerPlotConfig config) { - _configPane.addTab(config.getTitle(), null, new JScrollPane(new PeerPlotConfigPane(config, this)), config.getSummary()); - _configPane.setBackgroundAt(_configPane.getTabCount()-1, _background); - _configPane.setForegroundAt(_configPane.getTabCount()-1, _foreground); - _gui.pack(); - } - - /** - * Removes a test from the panel - * @param config the configuration for the test - */ - public void removeTest(PeerPlotConfig config) { - _gui.getMonitor().getState().removeTest(config); - int index = _configPane.indexOfTab(config.getTitle()); - if (index >= 0) - _configPane.removeTabAt(index); - } - - /** - * Callback: when tests have changed - */ - public void testsUpdated() { - List knownNames = new ArrayList(8); - for (int i = 0; i < _gui.getMonitor().getState().getTestCount(); i++) { - PeerPlotState state = _gui.getMonitor().getState().getTest(i); - String title = state.getPlotConfig().getTitle(); - knownNames.add(state.getPlotConfig().getTitle()); - if (_configPane.indexOfTab(title) >= 0) { - _log.debug("We already know about [" + title + "]"); - } else { - _log.info("The test [" + title + "] is new to us"); - PeerPlotConfigPane pane = new PeerPlotConfigPane(state.getPlotConfig(), this); - _configPane.addTab(state.getPlotConfig().getTitle(), null, new JScrollPane(pane), state.getPlotConfig().getSummary()); - _configPane.setBackgroundAt(_configPane.getTabCount()-1, _background); - _configPane.setForegroundAt(_configPane.getTabCount()-1, _foreground); - } - } - List toRemove = new ArrayList(4); - for (int i = 0; i < _configPane.getTabCount(); i++) { - if (knownNames.contains(_configPane.getTitleAt(i))) { - // noop - } else { - toRemove.add(_configPane.getTitleAt(i)); - } - } - for (int i = 0; i < toRemove.size(); i++) { - String title = (String)toRemove.get(i); - _log.info("Removing test [" + title + "]"); - _configPane.removeTabAt(_configPane.indexOfTab(title)); - } - } - - private void initializeComponents() { - if (_gui != null) - setBackground(_gui.getBackground()); - else - setBackground(_background); - setLayout(new BorderLayout()); - HeartbeatMonitorCommandBar bar = new HeartbeatMonitorCommandBar(_gui); - bar.setBackground(getBackground()); - add(bar, BorderLayout.NORTH); - _configPane = new JTabbedPane(JTabbedPane.LEFT); - _configPane.setBackground(_background); - //add(_configPane, BorderLayout.CENTER); - add(_configPane, BorderLayout.SOUTH); - } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitor.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitor.java deleted file mode 100644 index 827d93ef6..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitor.java +++ /dev/null @@ -1,116 +0,0 @@ -package net.i2p.heartbeat.gui; - -import net.i2p.util.I2PThread; -import net.i2p.util.Log; - -/** - * The HeartbeatMonitor, complete with main()! Act now, and it's only 5 easy - * payments of $19.95 (plus shipping and handling)! You heard me, only _5_ - * easy payments of $19.95 (plus shipping and handling)!

- * - * (fine print: something about some states in the US requiring the addition - * of sales tax... or something)

- * - * (finer print: Satan owns you. Deal with it.)

- * - * (even finer print: usage: HeartbeatMonitor [configFilename]) - */ -public class HeartbeatMonitor implements PeerPlotStateFetcher.FetchStateReceptor, PeerPlotConfig.UpdateListener { - private final static Log _log = new Log(HeartbeatMonitor.class); - private HeartbeatMonitorState _state; - private HeartbeatMonitorGUI _gui; - - /** - * Delegating constructor. - * @see HeartbeatMonitor#HeartbeatMonitor(String) - */ - public HeartbeatMonitor() { this(null); } - - /** - * Creates a HeartbeatMonitor . . . - * @param configFilename the configuration file to read from - */ - public HeartbeatMonitor(String configFilename) { - _state = new HeartbeatMonitorState(configFilename); - _gui = new HeartbeatMonitorGUI(this); - } - - /** - * Starts the game rollin' - */ - public void runMonitor() { - loadConfig(); - I2PThread t = new I2PThread(new HeartbeatMonitorRunner(this)); - t.setName("HeartbeatMonitor"); - t.setDaemon(false); - t.start(); - _log.debug("Monitor started"); - } - - /** - * give us all the data/config available - * @return the current state (data/config) - */ - HeartbeatMonitorState getState() { - return _state; - } - - /** for all of the peer tests being monitored, refetch the data and rerender */ - void refetchData() { - _log.debug("Refetching data"); - for (int i = 0; i < _state.getTestCount(); i++) - PeerPlotStateFetcher.fetchPeerPlotState(this, _state.getTest(i)); - } - - /** (re)load the config defining what peer tests we are monitoring (and how to render) */ - void loadConfig() { - //for (int i = 0; i < 10; i++) { - // load("fake" + i); - //} - } - - /** - * Loads config data - * @param location the name of the location to load data from - */ - public void load(String location) { - PeerPlotConfig cfg = new PeerPlotConfig(location); - cfg.addListener(this); - PeerPlotState state = new PeerPlotState(cfg); - PeerPlotStateFetcher.fetchPeerPlotState(this, state); - } - - /* (non-Javadoc) - * @see PeerPlotStateFetcher.FetchStateReceptor#peerPlotStateFetched - */ - public synchronized void peerPlotStateFetched(PeerPlotState state) { - _state.addTest(state); - _gui.stateUpdated(); - } - - /** - * store the config defining what peer tests we are monitoring (and how to render) - */ - void storeConfig() {} - - /** - * And now, the main function, the one you've all been waiting for! . . . - * @param args da args. Should take 1, which is the location to load config data from - */ - public static void main(String args[]) { - Thread.currentThread().setName("HeartbeatMonitor.main"); - if (args.length == 1) - new HeartbeatMonitor(args[0]).runMonitor(); - else - new HeartbeatMonitor().runMonitor(); - } - - /** - * Called when the config is updated - * @param config the updated config - */ - public void configUpdated(PeerPlotConfig config) { - _log.debug("Config updated, revamping the gui"); - _gui.stateUpdated(); - } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorCommandBar.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorCommandBar.java deleted file mode 100644 index c95aa68a3..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorCommandBar.java +++ /dev/null @@ -1,67 +0,0 @@ -package net.i2p.heartbeat.gui; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; - -import javax.swing.DefaultComboBoxModel; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; - -class HeartbeatMonitorCommandBar extends JPanel { - private HeartbeatMonitorGUI _gui; - private JComboBox _refreshRate; - private JTextField _location; - - /** - * Constructs a command bar onto the gui - * @param gui the gui the command bar is associated with - */ - public HeartbeatMonitorCommandBar(HeartbeatMonitorGUI gui) { - _gui = gui; - initializeComponents(); - } - - private void refreshChanged(ItemEvent evt) {} - private void loadCalled() { - _gui.getMonitor().load(_location.getText()); - } - - private void browseCalled() { - JFileChooser chooser = new JFileChooser(_location.getText()); - chooser.setBackground(_gui.getBackground()); - chooser.setMultiSelectionEnabled(false); - int rv = chooser.showDialog(this, "Load"); - if (rv == JFileChooser.APPROVE_OPTION) - _gui.getMonitor().load(chooser.getSelectedFile().getAbsolutePath()); - } - - private void initializeComponents() { - _refreshRate = new JComboBox(new DefaultComboBoxModel(new Object[] {"10 second refresh", "30 second refresh", "1 minute refresh", "5 minute refresh"})); - _refreshRate.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent evt) { refreshChanged(evt); } }); - _refreshRate.setEnabled(false); - _refreshRate.setBackground(_gui.getBackground()); - //add(_refreshRate); - JLabel loadLabel = new JLabel("Load from: "); - loadLabel.setBackground(_gui.getBackground()); - add(loadLabel); - _location = new JTextField(20); - _location.setToolTipText("Either specify a local filename or a fully qualified URL"); - _location.setBackground(_gui.getBackground()); - add(_location); - JButton browse = new JButton("Browse..."); - browse.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { browseCalled(); } }); - browse.setBackground(_gui.getBackground()); - add(browse); - JButton load = new JButton("Load"); - load.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { loadCalled(); } }); - load.setBackground(_gui.getBackground()); - add(load); - setBackground(_gui.getBackground()); - } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorGUI.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorGUI.java deleted file mode 100644 index 27786b1ff..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorGUI.java +++ /dev/null @@ -1,98 +0,0 @@ -package net.i2p.heartbeat.gui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JScrollPane; - -class HeartbeatMonitorGUI extends JFrame { - private HeartbeatMonitor _monitor; - private HeartbeatPlotPane _plotPane; - private HeartbeatControlPane _controlPane; - private final static Color WHITE = new Color(255, 255, 255); - private Color _background = WHITE; - - /** - * Creates the GUI for all youz who be too shoopid for text based shitz - * @param monitor the monitor the gui operates over - */ - public HeartbeatMonitorGUI(HeartbeatMonitor monitor) { - super("Heartbeat Monitor"); - _monitor = monitor; - initializeComponents(); - pack(); - //setResizable(false); - setVisible(true); - } - - HeartbeatMonitor getMonitor() { return _monitor; } - - /** build up all our widgets */ - private void initializeComponents() { - getContentPane().setLayout(new BorderLayout()); - - setBackground(_background); - - _plotPane = new JFreeChartHeartbeatPlotPane(this); // new HeartbeatPlotPane(this); - _plotPane.setBackground(_background); - //JScrollPane pane = new JScrollPane(_plotPane); - //pane.setBackground(_background); - getContentPane().add(new JScrollPane(_plotPane), BorderLayout.CENTER); - - _controlPane = new HeartbeatControlPane(this); - _controlPane.setBackground(_background); - getContentPane().add(_controlPane, BorderLayout.SOUTH); - - //JSplitPane pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(_plotPane), new JScrollPane(_controlPane)); - //getContentPane().add(pane, BorderLayout.CENTER); - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - initializeMenus(); - } - - /** - * Callback: when the state of the world changes . . . - */ - public void stateUpdated() { - _controlPane.testsUpdated(); - _plotPane.stateUpdated(); - } - - private void exitCalled() { - _monitor.getState().setWasKilled(true); - setVisible(false); - System.exit(0); - } - private void loadConfigCalled() {} - private void saveConfigCalled() {} - private void loadSnapshotCalled() {} - private void saveSnapshotCalled() {} - - private void initializeMenus() { - JMenuBar bar = new JMenuBar(); - JMenu fileMenu = new JMenu("File"); - JMenuItem loadConfig = new JMenuItem("Load config"); - loadConfig.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { loadConfigCalled(); } }); - JMenuItem saveConfig = new JMenuItem("Save config"); - saveConfig.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { saveConfigCalled(); } }); - JMenuItem saveSnapshot = new JMenuItem("Save snapshot"); - saveSnapshot.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { saveSnapshotCalled(); } }); - JMenuItem loadSnapshot = new JMenuItem("Load snapshot"); - loadSnapshot.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { loadSnapshotCalled(); } }); - JMenuItem exit = new JMenuItem("Exit"); - exit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { exitCalled(); } }); - - fileMenu.add(loadConfig); - fileMenu.add(saveConfig); - fileMenu.add(loadSnapshot); - fileMenu.add(saveSnapshot); - fileMenu.add(exit); - bar.add(fileMenu); - setJMenuBar(bar); - } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorRunner.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorRunner.java deleted file mode 100644 index 862fff271..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorRunner.java +++ /dev/null @@ -1,32 +0,0 @@ -package net.i2p.heartbeat.gui; - -import net.i2p.util.Log; - -/** - * Periodically fire off necessary events (instructing the heartbeat monitor when - * to refetch the data, etc). This is the only active thread in the heartbeat - * monitor (outside the swing/jvm threads) - */ -class HeartbeatMonitorRunner implements Runnable { - private final static Log _log = new Log(HeartbeatMonitorRunner.class); - private HeartbeatMonitor _monitor; - - /** - * Creates the thread . . . - * @param monitor the monitor the thread runs over - */ - public HeartbeatMonitorRunner(HeartbeatMonitor monitor) { - _monitor = monitor; - } - - /* (non-Javadoc) - * @see java.lang.Runnable#run() - */ - public void run() { - while (!_monitor.getState().getWasKilled()) { - _monitor.refetchData(); - try { Thread.sleep(_monitor.getState().getRefreshRateMs()); } catch (InterruptedException ie) {} - } - _log.info("Stopping the heartbeat monitor runner"); - } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorState.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorState.java deleted file mode 100644 index 7de4bc9bb..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatMonitorState.java +++ /dev/null @@ -1,129 +0,0 @@ -package net.i2p.heartbeat.gui; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * manage the current state of the GUI - all data points, as well as any - * rendering or configuration options. - */ -class HeartbeatMonitorState { - private String _configFile; - private List _peerPlotState; - private int _currentPeerPlotConfig; - private int _refreshRateMs; - private boolean _killed; - - /** by default, refresh every 30 seconds */ - private final static int DEFAULT_REFRESH_RATE = 30*1000; - /** where do we load/store config info from? */ - private final static String DEFAULT_CONFIG_FILE = "heartbeatMonitor.config"; - - /** - * A delegating constructor. - * @see HeartbeatMonitorState#HeartbeatMonitorState(String) - */ - public HeartbeatMonitorState() { this(DEFAULT_CONFIG_FILE); } - - /** - * Constructs the state, loading from the specified location - * @param configFile the name of the file to load info from - */ - public HeartbeatMonitorState(String configFile) { - _peerPlotState = Collections.synchronizedList(new ArrayList()); - _refreshRateMs = DEFAULT_REFRESH_RATE; - _configFile = configFile; - _killed = false; - _currentPeerPlotConfig = 0; - } - - /** - * how many tests are we monitoring? - * @return the number of tests - */ - public int getTestCount() { return _peerPlotState.size(); } - - /** - * Retrieves the current info of a test for a certain peer . . . - * @param peer a number associated with a certain peer - * @return the test data - */ - public PeerPlotState getTest(int peer) { return (PeerPlotState)_peerPlotState.get(peer); } - - /** - * Adds a test . . . - * @param peerState the test (by state) to add . . . - */ - public void addTest(PeerPlotState peerState) { - if (!_peerPlotState.contains(peerState)) - _peerPlotState.add(peerState); - } - /** - * Removes a test . . . - * @param peerState the test (by state) to remove . . . - */ - public void removeTest(PeerPlotState peerState) { _peerPlotState.remove(peerState); } - - /** - * Removes a test . . . - * @param peerConfig the test (by config) to remove . . . - */ - public void removeTest(PeerPlotConfig peerConfig) { - for (int i = 0; i < getTestCount(); i++) { - PeerPlotState state = getTest(i); - if (state.getPlotConfig() == peerConfig) { - removeTest(state); - return; - } - } - } - - /** - * which of the tests are we currently editing/viewing? - * @return the number associated with the test - */ - public int getPeerPlotConfig() { return _currentPeerPlotConfig; } - - /** - * Sets the test we are currently editting/viewing - * @param whichTest the number associated with the test - */ - public void setPeerPlotConfig(int whichTest) { _currentPeerPlotConfig = whichTest; } - - /** - * how frequently should we update the data? - * @return the current frequency (in milliseconds) - */ - public int getRefreshRateMs() { return _refreshRateMs; } - - /** - * Sets how frequently we should update data - * @param ms the frequency (in milliseconds) - */ - public void setRefreshRateMs(int ms) { _refreshRateMs = ms; } - - /** - * where is our config stored? - * @return the name of the config file - */ - public String getConfigFile() { return _configFile; } - - /** - * Sets where our config is stored - * @param filename the name of the config file - */ - public void setConfigFile(String filename) { _configFile = filename; } - - /** - * have we been shut down? - * @return true if we have, false otherwise - */ - public boolean getWasKilled() { return _killed; } - - /** - * Sets if we have been shutdown or not - * @param killed true if we've been shutdown, false otherwise - */ - public void setWasKilled(boolean killed) { _killed = killed; } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatPlotPane.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatPlotPane.java deleted file mode 100644 index 2cc122f0d..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/HeartbeatPlotPane.java +++ /dev/null @@ -1,62 +0,0 @@ -package net.i2p.heartbeat.gui; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import javax.swing.JPanel; -import javax.swing.JTextArea; - -import net.i2p.heartbeat.PeerDataWriter; -import net.i2p.util.Log; - -/** - * Render the graph and legend - */ -class HeartbeatPlotPane extends JPanel { - private final static Log _log = new Log(HeartbeatPlotPane.class); - protected HeartbeatMonitorGUI _gui; - private JTextArea _text; - - /** - * Constructs the plot pane - * @param gui the gui the pane is attached to - */ - public HeartbeatPlotPane(HeartbeatMonitorGUI gui) { - _gui = gui; - initializeComponents(); - } - - /** - * Callback: when things change . . . - */ - public void stateUpdated() { - StringBuffer buf = new StringBuffer(32*1024); - PeerDataWriter writer = new PeerDataWriter(); - - for (int i = 0; i < _gui.getMonitor().getState().getTestCount(); i++) { - StaticPeerData data = _gui.getMonitor().getState().getTest(i).getCurrentData(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); - try { - writer.persist(data, baos); - } catch (IOException ioe) { - _log.error("wtf, error writing to a byte array?", ioe); - } - buf.append(new String(baos.toByteArray())).append("\n\n\n"); - } - - _text.setText(buf.toString()); - } - - protected void initializeComponents() { - setBackground(_gui.getBackground()); - //Dimension size = new Dimension(800, 600); - _text = new JTextArea("",30,80); // 16, 60); - _text.setAutoscrolls(true); - _text.setEditable(false); - // _text.setLineWrap(true); - // add(new JScrollPane(_text)); - add(_text); - // add(new JScrollPane(_text, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS)); - // setPreferredSize(size); - } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartAdapter.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartAdapter.java deleted file mode 100644 index 80ef31ca7..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartAdapter.java +++ /dev/null @@ -1,233 +0,0 @@ -package net.i2p.heartbeat.gui; - -import java.awt.Color; -import java.awt.Font; -import java.util.List; - -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.DateAxis; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.plot.Plot; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.XYItemRenderer; -import org.jfree.chart.renderer.XYLineAndShapeRenderer; -import org.jfree.data.XYSeries; -import org.jfree.data.XYSeriesCollection; - -import net.i2p.heartbeat.PeerData; -import net.i2p.util.Log; - -class JFreeChartAdapter { - private final static Log _log = new Log(JFreeChartAdapter.class); /* UNUSED */ - private final static Color WHITE = new Color(255, 255, 255); - - ChartPanel createPanel(HeartbeatMonitorState state) { - ChartPanel panel = new ChartPanel(createChart(state)); - panel.setDisplayToolTips(true); - panel.setEnforceFileExtensions(true); - panel.setHorizontalZoom(true); - panel.setVerticalZoom(true); - panel.setMouseZoomable(true, true); - panel.getChart().setBackgroundPaint(WHITE); - return panel; - } - - JFreeChart createChart(HeartbeatMonitorState state) { - Plot plot = createPlot(state); - JFreeChart chart = new JFreeChart("I2P Heartbeat performance", Font.getFont("arial"), plot, true); - return chart; - } - - void updateChart(ChartPanel panel, HeartbeatMonitorState state) { - XYPlot plot = (XYPlot)panel.getChart().getPlot(); - plot.setDataset(getCollection(state)); - updateLines(plot, state); - } - - private long getFirst(HeartbeatMonitorState state) { /* UNUSED */ - long first = -1; - for (int i = 0; i < state.getTestCount(); i++) { - List dataPoints = state.getTest(i).getCurrentData().getDataPoints(); - if ( (dataPoints != null) && (dataPoints.size() > 0) ) { - PeerData.EventDataPoint data = (PeerData.EventDataPoint)dataPoints.get(0); - if ( (first < 0) || (first > data.getPingSent()) ) - first = data.getPingSent(); - } - } - return first; - } - - Plot createPlot(HeartbeatMonitorState state) { - XYItemRenderer renderer = new XYLineAndShapeRenderer(); // new XYDotRenderer(); // - XYPlot plot = new XYPlot(getCollection(state), new DateAxis(), new NumberAxis("ms"), renderer); - updateLines(plot, state); - return plot; - } - - private void updateLines(XYPlot plot, HeartbeatMonitorState state) { - if (true) return; - if (state == null) return; - for (int i = 0; i < state.getTestCount(); i++) { - PeerPlotConfig config = state.getTest(i).getPlotConfig(); - PeerPlotConfig.PlotSeriesConfig curConfig = config.getCurrentSeriesConfig(); - XYSeriesCollection col = ((XYSeriesCollection)plot.getDataset()); - for (int j = 0; j < col.getSeriesCount(); j++) { - //XYItemRenderer renderer = plot.getRendererForDataset(col.getSeries(j)); - XYItemRenderer renderer = plot.getRendererForDataset(col); - if (col.getSeriesName(j).startsWith(config.getTitle() + " send")) { - if (curConfig.getPlotSendTime()) { - //renderer.setPaint(curConfig.getPlotLineColor()); - } - } - if (col.getSeriesName(j).startsWith(config.getTitle() + " receive")) { - if (curConfig.getPlotReceiveTime()) { - //renderer.setPaint(curConfig.getPlotLineColor()); - } - } - if (col.getSeriesName(j).startsWith(config.getTitle() + " lost")) { - if (curConfig.getPlotLostMessages()) { - //renderer.setPaint(curConfig.getPlotLineColor()); - } - } - } - } - } - - XYSeriesCollection getCollection(HeartbeatMonitorState state) { - XYSeriesCollection col = new XYSeriesCollection(); - if (state != null) { - for (int i = 0; i < state.getTestCount(); i++) { - addTest(col, state.getTest(i)); - } - } else { - XYSeries series = new XYSeries("latency", false, false); - series.add(System.currentTimeMillis(), 0); - col.addSeries(series); - } - return col; - } - - void addTest(XYSeriesCollection col, PeerPlotState state) { - PeerPlotConfig config = state.getPlotConfig(); - PeerPlotConfig.PlotSeriesConfig curConfig = config.getCurrentSeriesConfig(); - addLines(col, curConfig, config.getTitle(), state.getCurrentData().getDataPoints()); - addAverageLines(col, config, config.getTitle(), state.getCurrentData()); - } - - /** - * @param col the collection of xy series to add to - * @param config preferences for how to display this test - * @param lineName minimal name of the test (e.g. "jxHa.32KB.60s") - * @param data List of PeerData.EventDataPoint describing all of the events in the test - */ - void addLines(XYSeriesCollection col, PeerPlotConfig.PlotSeriesConfig config, String lineName, List data) { - if (config.getPlotSendTime()) { - XYSeries sendSeries = getSendSeries(data); - sendSeries.setName(lineName + " send"); - sendSeries.setDescription("milliseconds for the ping to reach the peer"); - col.addSeries(sendSeries); - } - if (config.getPlotReceiveTime()) { - XYSeries recvSeries = getReceiveSeries(data); - recvSeries.setName(lineName + " receive"); - recvSeries.setDescription("milliseconds for the peer's pong to reach the sender"); - col.addSeries(recvSeries); - } - if (config.getPlotLostMessages()) { - XYSeries lostSeries = getLostSeries(data); - lostSeries.setName(lineName + " lost"); - lostSeries.setDescription("number of ping/pong messages lost"); - col.addSeries(lostSeries); - } - } - - /** - * Add a data series for each average that we're configured to render - * - * @param col the collection of xy series to add to - * @param config preferences for how to display this test - * @param lineName minimal name of the test (e.g. "jxHa.32KB.60s") - * @param data List of PeerData.EventDataPoint describing all of the events in the test - */ - void addAverageLines(XYSeriesCollection col, PeerPlotConfig config, String lineName, StaticPeerData data) { - if (data.getDataPointCount() <= 0) return; - PeerData.EventDataPoint start = (PeerData.EventDataPoint)data.getDataPoints().get(0); - PeerData.EventDataPoint finish = (PeerData.EventDataPoint)data.getDataPoints().get(data.getDataPointCount()-1); - - List configs = config.getAverageSeriesConfigs(); - - for (int i = 0; i < configs.size(); i++) { - PeerPlotConfig.PlotSeriesConfig cfg = (PeerPlotConfig.PlotSeriesConfig)configs.get(i); - int minutes = (int)cfg.getPeriod()/(60*1000); - if (cfg.getPlotSendTime()) { - double time = data.getAverageSendTime(minutes); - if (time > 0) { - XYSeries series = new XYSeries(lineName + " send " + minutes + "m avg [" + time + "]", false, false); - series.add(start.getPingSent(), time); - series.add(finish.getPingSent(), time); - series.setDescription("send time, averaged over the last " + minutes + " minutes"); - col.addSeries(series); - } - } - if (cfg.getPlotReceiveTime()) { - double time = data.getAverageReceiveTime(minutes); - if (time > 0) { - XYSeries series = new XYSeries(lineName + " receive " + minutes + "m avg[" + time + "]", false, false); - series.add(start.getPingSent(), time); - series.add(finish.getPingSent(), time); - series.setDescription("receive time, averaged over the last " + minutes + " minutes"); - col.addSeries(series); - } - } - if (cfg.getPlotLostMessages()) { - double num = data.getLostMessages(minutes); - if (num > 0) { - XYSeries series = new XYSeries(lineName + " lost messages (" + num + " in " + minutes + "m)", false, false); - series.add(start.getPingSent(), num); - series.add(finish.getPingSent(), num); - series.setDescription("number of messages lost in the last " + minutes + " minutes"); - col.addSeries(series); - } - } - } - } - - XYSeries getSendSeries(List data) { - XYSeries series = new XYSeries("sent", false, false); - for (int i = 0; i < data.size(); i++) { - PeerData.EventDataPoint point = (PeerData.EventDataPoint)data.get(i); - if (point.getWasPonged()) { - series.add(point.getPingSent(), point.getPongSent()-point.getPingSent()); - } else { - // series.add(data.getPingSent(), 0); - } - } - return series; - } - - XYSeries getReceiveSeries(List data) { - XYSeries series = new XYSeries("receive", false, false); - for (int i = 0; i < data.size(); i++) { - PeerData.EventDataPoint point = (PeerData.EventDataPoint)data.get(i); - if (point.getWasPonged()) { - series.add(point.getPingSent(), point.getPongReceived()-point.getPongSent()); - } else { - // series.add(data.getPingSent(), 0); - } - } - return series; - } - XYSeries getLostSeries(List data) { - XYSeries series = new XYSeries("lost", false, false); - for (int i = 0; i < data.size(); i++) { - PeerData.EventDataPoint point = (PeerData.EventDataPoint)data.get(i); - if (point.getWasPonged()) { - //series.add(point.getPingSent(), 0); - } else { - series.add(point.getPingSent(), 1); - } - } - return series; - } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartHeartbeatPlotPane.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartHeartbeatPlotPane.java deleted file mode 100644 index 7075c37d1..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/JFreeChartHeartbeatPlotPane.java +++ /dev/null @@ -1,58 +0,0 @@ -package net.i2p.heartbeat.gui; - -import java.awt.BorderLayout; - -import javax.swing.JLabel; -import javax.swing.JScrollPane; - -import org.jfree.chart.ChartPanel; - -import net.i2p.util.Log; - -/** - * Render the graph and legend - * - */ -class JFreeChartHeartbeatPlotPane extends HeartbeatPlotPane { - private final static Log _log = new Log(JFreeChartHeartbeatPlotPane.class); /* UNUSED */ - private ChartPanel _panel; - private JFreeChartAdapter _adapter; - - /** - * Creates a JFreeChart plot pane for the given gui - * @param gui the heartbeat monitor gui - */ - public JFreeChartHeartbeatPlotPane(HeartbeatMonitorGUI gui) { - super(gui); - } - - /** - * Called when the state is updated - */ - public void stateUpdated() { - if (_panel == null) { - remove(0); // remove the dummy - - _adapter = new JFreeChartAdapter(); - _panel = _adapter.createPanel(_gui.getMonitor().getState()); - _panel.setBackground(_gui.getBackground()); - add(new JScrollPane(_panel), BorderLayout.CENTER); - _gui.pack(); - } else { - _adapter.updateChart(_panel, _gui.getMonitor().getState()); - //_gui.pack(); - } - } - - protected void initializeComponents() { - // noop - setLayout(new BorderLayout()); - add(new JLabel(), BorderLayout.CENTER); - //dummy.setBackground(_gui.getBackground()); - //dummy.setPreferredSize(new Dimension(800,600)); - //add(dummy); - - //add(_panel); - - } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfig.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfig.java deleted file mode 100644 index 27d8533ae..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfig.java +++ /dev/null @@ -1,367 +0,0 @@ -package net.i2p.heartbeat.gui; - -import java.awt.Color; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.TreeMap; - -import net.i2p.data.Destination; -import net.i2p.heartbeat.ClientConfig; -import net.i2p.util.Log; - -/** - * Configure how we want to render a particular clientConfig in the GUI - */ -class PeerPlotConfig { - private final static Log _log = new Log(PeerPlotConfig.class); /* UNUSED */ - /** where can we find the current state/data (either as a filename or a URL)? */ - private String _location; - /** what test are we defining the plot data for? */ - private ClientConfig _config; - /** how should we render the current data set? */ - private PlotSeriesConfig _currentSeriesConfig; - /** how should we render the various averages available? */ - private List _averageSeriesConfigs; - private Set _listeners; - private boolean _disabled; - - /** - * Delegating constructor . . . - * @param location the name of the file/URL to get the data from - */ - public PeerPlotConfig(String location) { - this(location, null, null, null); - } - - /** - * Constructs a config =) - * @param location the location of the file/URL to get the data from - * @param config the client's configuration - * @param currentSeriesConfig the series config - * @param averageSeriesConfigs the average - */ - public PeerPlotConfig(String location, ClientConfig config, PlotSeriesConfig currentSeriesConfig, List averageSeriesConfigs) { - _location = location; - if (config == null) - config = new ClientConfig(location); - _config = config; - if (currentSeriesConfig != null) - _currentSeriesConfig = currentSeriesConfig; - else - _currentSeriesConfig = new PlotSeriesConfig(0); - - if (averageSeriesConfigs != null) { - _averageSeriesConfigs = averageSeriesConfigs; - } else { - rebuildAverageSeriesConfigs(); - } - _listeners = Collections.synchronizedSet(new HashSet(2)); - _disabled = false; - } - - /** - * 'Rebuilds' the average series stuff from the client configuration - */ - public void rebuildAverageSeriesConfigs() { - int periods[] = _config.getAveragePeriods(); - if (periods == null) { - _averageSeriesConfigs = Collections.synchronizedList(new ArrayList(0)); - } else { - Arrays.sort(periods); - _averageSeriesConfigs = Collections.synchronizedList(new ArrayList(periods.length)); - for (int i = 0; i < periods.length; i++) { - _averageSeriesConfigs.add(new PlotSeriesConfig(periods[i]*60*1000)); - } - } - } - - /** - * Adds an average period - * @param minutes the number of minutes averaged over - */ - public void addAverage(int minutes) { - _config.addAveragePeriod(minutes); - - TreeMap ordered = new TreeMap(); - for (int i = 0; i < _averageSeriesConfigs.size(); i++) { - PlotSeriesConfig cfg = (PlotSeriesConfig)_averageSeriesConfigs.get(i); - ordered.put(new Long(cfg.getPeriod()), cfg); - } - Long period = new Long(minutes*60*1000); - if (!ordered.containsKey(period)) - ordered.put(period, new PlotSeriesConfig(minutes*60*1000)); - - List cfgs = Collections.synchronizedList(new ArrayList(ordered.size())); - for (Iterator iter = ordered.values().iterator(); iter.hasNext(); ) - cfgs.add(iter.next()); - - _averageSeriesConfigs = cfgs; - } - - /** - * Where is the current state data supposed to be found? This must either be a - * local file path or a URL - * @return the current location - */ - public String getLocation() { return _location; } - - /** - * The location the current state data is supposed to be found. This must either be - * a local file path or a URL - * @param location the location - */ - public void setLocation(String location) { - _location = location; - fireUpdate(); - } - - /** - * What are we configuring? - * @return the client configuration - */ - public ClientConfig getClientConfig() { return _config; } - - /** - * Sets what we are currently configuring - * @param config the new config - */ - public void setClientConfig(ClientConfig config) { - _config = config; - fireUpdate(); - } - - /** - * How do we want to render the current data set? - * @return the way we currently render the data - */ - public PlotSeriesConfig getCurrentSeriesConfig() { return _currentSeriesConfig; } - - /** - * Sets how we want to render the current data set. - * @param config the new config - */ - public void setCurrentSeriesConfig(PlotSeriesConfig config) { - _currentSeriesConfig = config; - fireUpdate(); - } - - /** - * How do we want to render the averages? - * @return the way we currently render the averages - */ - public List getAverageSeriesConfigs() { return _averageSeriesConfigs; } - - /** - * Sets how we want to render the averages - * @param configs the new configs - */ - public void setAverageSeriesConfigs(List configs) { _averageSeriesConfigs = configs; } - - /** - * four char description of the peer - * @return the name - */ - public String getPeerName() { - Destination peer = getClientConfig().getPeer(); - if (peer == null) - return "????"; - - return peer.calculateHash().toBase64().substring(0, 4); - } - - /** - * title: name.packetsize.sendfrequency - * @return the title - */ - public String getTitle() { - return getPeerName() + '.' + getSize() + '.' + getClientConfig().getSendFrequency(); - } - - /** - * summary. includes:name, size, sendfrequency, and # of hops - * @return the summary - */ - public String getSummary() { - return "Send peer " + getPeerName() + ' ' + getSize() + " every " + - getClientConfig().getSendFrequency() + " seconds through " + - getClientConfig().getNumHops() + "-hop tunnels"; - } - - private String getSize() { - int bytes = getClientConfig().getSendSize(); - if (bytes < 1024) - return bytes + "b"; - - return bytes/1024 + "kb"; - } - - /** - * we've got someone who wants to be notified of changes to the plot config - * @param lsnr the listener to be added - */ - public void addListener(UpdateListener lsnr) { _listeners.add(lsnr); } - - /** - * remove a listener - * @param lsnr the listener to remove - */ - public void removeListener(UpdateListener lsnr) { _listeners.remove(lsnr); } - - void fireUpdate() { - if (_disabled) return; - for (Iterator iter = _listeners.iterator(); iter.hasNext(); ) { - ((UpdateListener)iter.next()).configUpdated(this); - } - } - - /** - * Disables notification of events listeners - * @see PeerPlotConfig#fireUpdate() - */ - public void disableEvents() { _disabled = true; } - - /** - * Enables notification of events listeners - * @see PeerPlotConfig#fireUpdate() - */ - public void enableEvents() { _disabled = false; } - - /** - * How do we want to render a particular dataset (either the current or the averaged values)? - */ - public class PlotSeriesConfig { - private long _period; - private boolean _plotSendTime; - private boolean _plotReceiveTime; - private boolean _plotLostMessages; - private Color _plotLineColor; - - /** - * Delegating constructor . . . - * @param period the period for the config - * (0 for current, otherwise # of milliseconds being averaged over) - */ - public PlotSeriesConfig(long period) { - this(period, false, false, false, null); - if (period <= 0) { - _plotSendTime = true; - _plotReceiveTime = true; - _plotLostMessages = true; - } - } - - - /** - * Creates a config for the rendering of a particular dataset) - * @param period the period for the config - * (0 for current, otherwise # of milliseconds being averaged over) - * @param plotSend do we plot send times? - * @param plotReceive do we plot receive times? - * @param plotLost do we plot lost packets? - * @param plotColor in what color? - */ - public PlotSeriesConfig(long period, boolean plotSend, boolean plotReceive, boolean plotLost, Color plotColor) { - _period = period; - _plotSendTime = plotSend; - _plotReceiveTime = plotReceive; - _plotLostMessages = plotLost; - _plotLineColor = plotColor; - } - - /** - * Retrieves the plot config this plot series config is a part of - * @return the plot config - */ - public PeerPlotConfig getPlotConfig() { return PeerPlotConfig.this; } - - /** - * What period is this series config describing? - * @return 0 for current, otherwise # milliseconds that are being averaged over - */ - public long getPeriod() { return _period; } - - /** - * Sets the period this series config is describing - * @param period the period - * (0 for current, otherwise # milliseconds that are being averaged over) - */ - public void setPeriod(long period) { - _period = period; - fireUpdate(); - } - - /** - * Should we render the time to send (ping to peer)? - * @return true or false . . . - */ - public boolean getPlotSendTime() { return _plotSendTime; } - - /** - * Sets whether we render the time to send (ping to peer) or not - * @param shouldPlot true or false - */ - public void setPlotSendTime(boolean shouldPlot) { - _plotSendTime = shouldPlot; - fireUpdate(); - } - - /** - * Should we render the time to receive (peer pong to us)? - * @return true or false . . . - */ - public boolean getPlotReceiveTime() { return _plotReceiveTime; } - - /** - * Sets whether we render the time to receive (peer pong to us) - * @param shouldPlot true or false - */ - public void setPlotReceiveTime(boolean shouldPlot) { - _plotReceiveTime = shouldPlot; - fireUpdate(); - } - /** - * Should we render the number of messages lost (ping sent, no pong received in time)? - * @return true or false . . . - */ - public boolean getPlotLostMessages() { return _plotLostMessages; } - - /** - * Sets whether we render the number of messages lost (ping sent, no pong received in time) or not - * @param shouldPlot true or false - */ - public void setPlotLostMessages(boolean shouldPlot) { - _plotLostMessages = shouldPlot; - fireUpdate(); - } - /** - * What color should we plot the data with? - * @return the color - */ - public Color getPlotLineColor() { return _plotLineColor; } - - /** - * Sets the color we should plot the data with - * @param color the color to use - */ - public void setPlotLineColor(Color color) { - _plotLineColor = color; - fireUpdate(); - } - } - - /** - * An interface for listening to updates . . . - */ - public interface UpdateListener { - /** - * @param config the peer plot config that changes - * @see PeerPlotConfig#fireUpdate() - */ - void configUpdated(PeerPlotConfig config); - } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfigPane.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfigPane.java deleted file mode 100644 index aa0ab1cde..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotConfigPane.java +++ /dev/null @@ -1,371 +0,0 @@ -package net.i2p.heartbeat.gui; - -import java.awt.Color; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; -import java.util.Random; - -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JColorChooser; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.JTextField; - -import net.i2p.util.Log; - -class PeerPlotConfigPane extends JPanel implements PeerPlotConfig.UpdateListener { - private final static Log _log = new Log(PeerPlotConfigPane.class); - private PeerPlotConfig _config; - private HeartbeatControlPane _parent; - private JLabel _title; - private JButton _delete; - private JLabel _fromLabel; - private JTextField _from; - private JTextArea _comments; - private JLabel _peerLabel; - private JTextField _peerKey; - private JLabel _localLabel; - private JTextField _localKey; - private OptionLine _options[]; - private Random _rnd = new Random(); - private final static Color WHITE = new Color(255, 255, 255); - private Color _background = WHITE; - - /** - * Constructs a pane - * @param config the plot config it represents - * @param pane the pane this one is attached to - */ - public PeerPlotConfigPane(PeerPlotConfig config, HeartbeatControlPane pane) { - _config = config; - _parent = pane; - if (_parent != null) - _background = _parent.getBackground(); - _config.addListener(this); - initializeComponents(); - } - - /** called when the user wants to stop monitoring this test */ - private void delete() { - _parent.removeTest(_config); - } - - private void initializeComponents() { - buildComponents(); - placeComponents(this); - refreshView(); - //setBorder(new BevelBorder(BevelBorder.RAISED)); - setBackground(_background); - } - - /** - * place all the gui components onto the given panel - * @param body the panel to place the components on - */ - private void placeComponents(JPanel body) { - body.setLayout(new GridBagLayout()); - GridBagConstraints cts = new GridBagConstraints(); - - // row 0: title + delete - cts.gridx = 0; - cts.gridy = 0; - cts.gridwidth = 5; - cts.anchor = GridBagConstraints.WEST; - cts.fill = GridBagConstraints.NONE; - body.add(_title, cts); - cts.gridx = 5; - cts.gridwidth = 1; - cts.anchor = GridBagConstraints.NORTHWEST; - cts.fill = GridBagConstraints.BOTH; - body.add(_delete, cts); - - // row 1: from + location - cts.gridx = 0; - cts.gridy = 1; - cts.gridwidth = 1; - cts.fill = GridBagConstraints.NONE; - body.add(_fromLabel, cts); - cts.gridx = 1; - cts.gridwidth = 5; - cts.fill = GridBagConstraints.BOTH; - body.add(_from, cts); - - // row 2: comment - cts.gridx = 0; - cts.gridy = 2; - cts.gridwidth = 6; - cts.fill = GridBagConstraints.BOTH; - body.add(_comments, cts); - - // row 3: peer + peerKey - cts.gridx = 0; - cts.gridy = 3; - cts.gridwidth = 1; - cts.fill = GridBagConstraints.NONE; - body.add(_peerLabel, cts); - cts.gridx = 1; - cts.gridwidth = 5; - cts.fill = GridBagConstraints.BOTH; - body.add(_peerKey, cts); - - // row 4: local + localKey - cts.gridx = 0; - cts.gridy = 4; - cts.gridwidth = 1; - cts.fill = GridBagConstraints.NONE; - body.add(_localLabel, cts); - cts.gridx = 1; - cts.gridwidth = 5; - cts.fill = GridBagConstraints.BOTH; - body.add(_localKey, cts); - - // row 5-N: data row - for (int i = 0; i < _options.length; i++) { - cts.gridx = 0; - cts.gridy = 5 + i; - cts.gridwidth = 1; - cts.fill = GridBagConstraints.NONE; - cts.anchor = GridBagConstraints.WEST; - if (_options[i]._durationMinutes <= 0) - body.add(new JLabel("Data: "), cts); - else - body.add(new JLabel(_options[i]._durationMinutes + "m avg: "), cts); - - cts.gridx = 1; - body.add(_options[i]._send, cts); - cts.gridx = 2; - body.add(_options[i]._recv, cts); - cts.gridx = 3; - body.add(_options[i]._lost, cts); - cts.gridx = 4; - body.add(_options[i]._all, cts); - cts.gridx = 5; - body.add(_options[i]._color, cts); - } - } - - /** build all of the gui components */ - private void buildComponents() { - _title = new JLabel(_config.getSummary()); - _title.setBackground(_background); - _delete = new JButton("Delete"); - _delete.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { delete(); } }); - _delete.setEnabled(false); - _delete.setBackground(_background); - _fromLabel = new JLabel("Location: "); - _fromLabel.setBackground(_background); - _from = new JTextField(_config.getLocation()); - _from.setEditable(false); - _from.setBackground(_background); - _comments = new JTextArea(_config.getClientConfig().getComment(), 2, 20); - // _comments = new JTextArea(_config.getClientConfig().getComment(), 2, 40); - _comments.setEditable(false); - _comments.setBackground(_background); - _peerLabel = new JLabel("Peer: "); - _peerLabel.setBackground(_background); - _peerKey = new JTextField(_config.getClientConfig().getPeer().toBase64(), 8); - _peerKey.setBackground(_background); - _localLabel = new JLabel("Local: "); - _localLabel.setBackground(_background); - _localKey = new JTextField(_config.getClientConfig().getUs().toBase64(), 8); - _localKey.setBackground(_background); - - int averagedPeriods[] = _config.getClientConfig().getAveragePeriods(); - if (averagedPeriods == null) - averagedPeriods = new int[0]; - - _options = new OptionLine[1 + averagedPeriods.length]; - _options[0] = new OptionLine(0); - for (int i = 0; i < averagedPeriods.length; i++) { - _options[1+i] = new OptionLine(averagedPeriods[i]); - } - } - - /** the settings have changed - revise */ - private void refreshView() { - for (int i = 0; i < _options.length; i++) { - PeerPlotConfig.PlotSeriesConfig cfg = getConfig(_options[i]._durationMinutes); - if (cfg == null) { - _log.warn("Config for minutes " + _options[i]._durationMinutes + " was not found?"); - continue; - } - //_log.debug("Refreshing view for minutes ["+ _options[i]._durationMinutes + "]: send [" + - // _options[i]._send.isSelected() + "/" + cfg.getPlotSendTime() + "] recv [" + - // _options[i]._recv.isSelected() + "/" + cfg.getPlotReceiveTime() + "] lost [" + - // _options[i]._lost.isSelected() + "/" + cfg.getPlotLostMessages() + "]"); - _options[i]._send.setSelected(cfg.getPlotSendTime()); - _options[i]._recv.setSelected(cfg.getPlotReceiveTime()); - _options[i]._lost.setSelected(cfg.getPlotLostMessages()); - if (cfg.getPlotLineColor() != null) - _options[i]._color.setBackground(cfg.getPlotLineColor()); - } - } - - /** - * find the right config for the given period - * @param minutes the minutes to locate the config by - * @return the config for the given period, or null - */ - private PeerPlotConfig.PlotSeriesConfig getConfig(int minutes) { - if (minutes <= 0) - return _config.getCurrentSeriesConfig(); - - List configs = _config.getAverageSeriesConfigs(); - for (int i = 0; i < configs.size(); i++) { - PeerPlotConfig.PlotSeriesConfig cfg = (PeerPlotConfig.PlotSeriesConfig)configs.get(i); - if (cfg.getPeriod() == minutes * 60*1000) - return cfg; - } - return null; - } - - /** - * notified that the config has been updated - * @param config the config that was been updated - */ - public void configUpdated(PeerPlotConfig config) { refreshView(); } - - private class ChooseColor implements ActionListener { - private int _minutes; - private JButton _button; - - /** - * @param minutes the minutes (line) to change the color of... - * @param button the associated button - */ - public ChooseColor(int minutes, JButton button) { - _minutes = minutes; - _button = button; - } - - /* (non-Javadoc) - * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) - */ - public void actionPerformed(ActionEvent evt) { - PeerPlotConfig.PlotSeriesConfig cfg = getConfig(_minutes); - Color origColor = null; - if (cfg != null) - origColor = cfg.getPlotLineColor(); - Color color = JColorChooser.showDialog(PeerPlotConfigPane.this, "What color should this line be?", origColor); - if (color != null) { - if (cfg != null) - cfg.setPlotLineColor(color); - _button.setBackground(color); - } - } - } - - private class OptionLine { - int _durationMinutes; - JCheckBox _send; - JCheckBox _recv; - JCheckBox _lost; - JCheckBox _all; - JButton _color; - - /** - * Creates an OptionLine. - * @param durationMinutes the minutes =) - */ - public OptionLine(int durationMinutes) { - _durationMinutes = durationMinutes; - _send = new JCheckBox("send time"); - _send.setBackground(_background); - _recv = new JCheckBox("receive time"); - _recv.setBackground(_background); - _lost = new JCheckBox("lost messages"); - _lost.setBackground(_background); - _all = new JCheckBox("all"); - _all.setBackground(_background); - _color = new JButton("color"); - int r = _rnd.nextInt(255); - if (r < 0) r = -r; - int g = _rnd.nextInt(255); - if (g < 0) g = -g; - int b = _rnd.nextInt(255); - if (b < 0) b = -b; - //_color.setBackground(new Color(r, g, b)); - _color.setBackground(_background); - - _send.addActionListener(new UpdateListener(OptionLine.this, _durationMinutes)); - _recv.addActionListener(new UpdateListener(OptionLine.this, _durationMinutes)); - _lost.addActionListener(new UpdateListener(OptionLine.this, _durationMinutes)); - _all.addActionListener(new UpdateListener(OptionLine.this, _durationMinutes)); - _color.addActionListener(new ChooseColor(durationMinutes, _color)); - _color.setEnabled(false); - } - } - - private class UpdateListener implements ActionListener { - private OptionLine _line; - private int _minutes; - - /** - * Update Listener constructor . . . - * @param line the line - * @param minutes the minutes - */ - public UpdateListener(OptionLine line, int minutes) { - _line = line; - _minutes = minutes; - } - - /* (non-Javadoc) - * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) - */ - public void actionPerformed(ActionEvent evt) { - PeerPlotConfig.PlotSeriesConfig cfg = getConfig(_minutes); - - cfg.getPlotConfig().disableEvents(); - _log.debug("Updating data for minutes ["+ _line._durationMinutes + "]: send [" + - _line._send.isSelected() + "/" + cfg.getPlotSendTime() + "] recv [" + - _line._recv.isSelected() + "/" + cfg.getPlotReceiveTime() + "] lost [" + - _line._lost.isSelected() + "/" + cfg.getPlotLostMessages() + "]: config = " + cfg); - - boolean force = _line._all.isSelected(); - cfg.setPlotSendTime(_line._send.isSelected() || force); - cfg.setPlotReceiveTime(_line._recv.isSelected() || force); - cfg.setPlotLostMessages(_line._lost.isSelected() || force); - cfg.getPlotConfig().enableEvents(); - cfg.getPlotConfig().fireUpdate(); - } - } - - /** - * Unit test stuff - * @param args da arsg - */ - public final static void main(String args[]) { - Test t = new Test(); - t.runTest(); - } - - private final static class Test implements PeerPlotStateFetcher.FetchStateReceptor { - /** - * Runs da test - */ - public void runTest() { - PeerPlotConfig cfg = new PeerPlotConfig("C:\\testnet\\r2\\heartbeatStat_10s_30kb.txt"); - PeerPlotState state = new PeerPlotState(cfg); - PeerPlotStateFetcher.fetchPeerPlotState(this, state); - try { Thread.sleep(60*1000); } catch (InterruptedException ie) {} - System.exit(-1); - } - - /* (non-Javadoc) - * @see net.i2p.heartbeat.gui.PeerPlotStateFetcher.FetchStateReceptor#peerPlotStateFetched(net.i2p.heartbeat.gui.PeerPlotState) - */ - public void peerPlotStateFetched(PeerPlotState state) { - javax.swing.JFrame f = new javax.swing.JFrame("Test"); - f.getContentPane().add(new JScrollPane(new PeerPlotConfigPane(state.getPlotConfig(), null))); - f.pack(); - f.setVisible(true); - } - } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotState.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotState.java deleted file mode 100644 index d658081a3..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotState.java +++ /dev/null @@ -1,95 +0,0 @@ -package net.i2p.heartbeat.gui; - - -/** - * Current data + plot config for a particular test - * - */ -class PeerPlotState { - private StaticPeerData _currentData; - private PeerPlotConfig _plotConfig; - - /** - * Delegating constructor . . . - * @see PeerPlotState#PeerPlotState(PeerPlotConfig, StaticPeerData) - */ - public PeerPlotState() { - this(null, null); - } - - /** - * Delegating constructor . . . - * @param config plot config - * @see PeerPlotState#PeerPlotState(PeerPlotConfig, StaticPeerData) - */ - public PeerPlotState(PeerPlotConfig config) { - this(config, new StaticPeerData(config.getClientConfig())); - } - /** - * Creates a PeerPlotState - * @param config plot config - * @param data peer data - */ - public PeerPlotState(PeerPlotConfig config, StaticPeerData data) { - _plotConfig = config; - _currentData = data; - } - - /** - * Add an average - * @param minutes mins averaged over - * @param sendMs how much later did the peer receieve - * @param recvMs how much later did we receieve - * @param lost how many were lost - */ - public void addAverage(int minutes, int sendMs, int recvMs, int lost) { - // make sure we've got the config entry for the average - _plotConfig.addAverage(minutes); - // add the data point... - _currentData.addAverage(minutes, sendMs, recvMs, lost); - } - - /** - * we successfully got a ping/pong through - * - * @param sendTime when did the ping get sent? - * @param sendMs how much later did the peer receive the ping? - * @param recvMs how much later than that did we receive the pong? - */ - public void addSuccess(long sendTime, int sendMs, int recvMs) { - _currentData.addData(sendTime, sendMs, recvMs); - } - - /** - * we lost a ping/pong - * - * @param sendTime when did we send the ping? - */ - public void addLost(long sendTime) { - _currentData.addData(sendTime); - } - - /** - * data set to render - * @return the data set - */ - public StaticPeerData getCurrentData() { return _currentData; } - - /** - * Sets the data set to render - * @param data the data set - */ - public void setCurrentData(StaticPeerData data) { _currentData = data; } - - /** - * configuration options on how to render the data set - * @return the config options - */ - public PeerPlotConfig getPlotConfig() { return _plotConfig; } - - /** - * Sets the configuration options on how to render the data - * @param config the config options - */ - public void setPlotConfig(PeerPlotConfig config) { _plotConfig = config; } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotStateFetcher.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotStateFetcher.java deleted file mode 100644 index 82b5aa73a..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/PeerPlotStateFetcher.java +++ /dev/null @@ -1,363 +0,0 @@ -package net.i2p.heartbeat.gui; - -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.MalformedURLException; -import java.net.URL; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Locale; -import java.util.StringTokenizer; - -import net.i2p.data.DataFormatException; -import net.i2p.data.Destination; -import net.i2p.util.I2PThread; -import net.i2p.util.Log; - -class PeerPlotStateFetcher { - private final static Log _log = new Log(PeerPlotStateFetcher.class); - - /** - * Fetch and fill the specified state structure - * @param receptor the 'receptor' (callbacks) - * @param state the state - */ - public static void fetchPeerPlotState(FetchStateReceptor receptor, PeerPlotState state) { - I2PThread t = new I2PThread(new Fetcher(receptor, state)); - t.setDaemon(true); - t.setName("Fetch state from " + state.getPlotConfig().getLocation()); - t.start(); - } - - /** - * Callback stuff . . . - */ - public interface FetchStateReceptor { - /** - * Called when a peer plot state is fetched - * @param state state that was fetched - */ - void peerPlotStateFetched(PeerPlotState state); - } - - private static class Fetcher implements Runnable { - private PeerPlotState _state; - private FetchStateReceptor _receptor; - - /** - * Creates a Fetcher thread - * @param receptor the 'receptor' (callbacks) - * @param state the state - */ - public Fetcher(FetchStateReceptor receptor, PeerPlotState state) { - _state = state; - _receptor = receptor; - } - - /* (non-Javadoc) - * @see java.lang.Runnable#run() - */ - public void run() { - String loc = _state.getPlotConfig().getLocation(); - _log.debug("Load called [" + loc + "]"); - InputStream in = null; - try { - try { - URL location = new URL(loc); - in = location.openStream(); - } catch (MalformedURLException mue) { - _log.debug("Not a url [" + loc + "]"); - in = null; - } - - if (in == null) - in = new FileInputStream(loc); - - BufferedReader reader = new BufferedReader(new InputStreamReader(in)); - String line = null; - while ( (line = reader.readLine()) != null) { - handleLine(line); - } - - if (valid()) - _receptor.peerPlotStateFetched(_state); - } catch (IOException ioe) { - _log.error("Error retrieving from the location [" + loc + "]", ioe); - } finally { - if (in != null) try { in.close(); } catch (IOException ioe) {} - } - } - - /** - * check to make sure we've got everything we need - * @return true [always] - */ - boolean valid() { - return true; - } - - /** - * handle a line from the data set - these can be formatted in one of the - * following ways.

- * - *

-         * peer            khWYqCETu9YtPUvGV92ocsbEW5DezhKlIG7ci8RLX3g=
-         * local           u-9hlR1ik2hemXf0HvKMfeRgrS86CbNQh25e7XBhaQE=
-         * peerDest        [base 64 of the full destination]
-         * localDest       [base 64 of the full destination]
-         * numTunnelHops   2
-         * comment         Test with localhost sending 30KB every 20 seconds
-         * sendFrequency   20
-         * sendSize        30720
-         * sessionStart    20040409.22:51:10.915
-         * currentTime     20040409.23:31:39.607
-         * numPending      2
-         * lifetimeSent    118
-         * lifetimeRecv    113
-         * #averages       minutes sendMs  recvMs  numLost
-         * periodAverage   1       1843    771     0
-         * periodAverage   5       786     752     1
-         * periodAverage   30      855     735     3
-         * #action status  date and time sent      sendMs  replyMs
-         * EVENT   OK      20040409.23:21:44.742   691     670
-         * EVENT   OK      20040409.23:22:05.201   671     581
-         * EVENT   OK      20040409.23:22:26.301   1182    1452
-         * EVENT   OK      20040409.23:22:47.322   24304   1723
-         * EVENT   OK      20040409.23:23:08.232   2293    1081
-         * EVENT   OK      20040409.23:23:29.332   1392    641
-         * EVENT   OK      20040409.23:23:50.262   641     761
-         * EVENT   OK      20040409.23:24:11.102   651     701
-         * EVENT   OK      20040409.23:24:31.401   841     621
-         * EVENT   OK      20040409.23:24:52.061   651     681
-         * EVENT   OK      20040409.23:25:12.480   701     1623
-         * EVENT   OK      20040409.23:25:32.990   1442    1212
-         * EVENT   OK      20040409.23:25:54.230   591     631
-         * EVENT   OK      20040409.23:26:14.620   620     691
-         * EVENT   OK      20040409.23:26:35.199   1793    1432
-         * EVENT   OK      20040409.23:26:56.570   661     641
-         * EVENT   OK      20040409.23:27:17.200   641     660
-         * EVENT   OK      20040409.23:27:38.120   611     921
-         * EVENT   OK      20040409.23:27:58.699   831     621
-         * EVENT   OK      20040409.23:28:19.559   801     661
-         * EVENT   OK      20040409.23:28:40.279   601     611
-         * EVENT   OK      20040409.23:29:00.648   601     621
-         * EVENT   OK      20040409.23:29:21.288   701     661
-         * EVENT   LOST    20040409.23:29:41.828
-         * EVENT   LOST    20040409.23:30:02.327
-         * EVENT   LOST    20040409.23:30:22.656
-         * EVENT   OK      20040409.23:31:24.305   1843    771
-         * 
- * - * @param line (see above) - */ - private void handleLine(String line) { - if (line.startsWith("peerDest")) - handlePeerDest(line); - else if (line.startsWith("localDest")) - handleLocalDest(line); - else if (line.startsWith("numTunnelHops")) - handleNumTunnelHops(line); - else if (line.startsWith("comment")) - handleComment(line); - else if (line.startsWith("sendFrequency")) - handleSendFrequency(line); - else if (line.startsWith("sendSize")) - handleSendSize(line); - else if (line.startsWith("periodAverage")) - handlePeriodAverage(line); - else if (line.startsWith("EVENT")) - handleEvent(line); - else if (line.startsWith("numPending")) - handleNumPending(line); - else if (line.startsWith("sessionStart")) - handleSessionStart(line); - else - _log.debug("Not handled: " + line); - } - - private void handlePeerDest(String line) { - StringTokenizer tok = new StringTokenizer(line); - tok.nextToken(); // ignore; - String destKey = tok.nextToken(); - try { - Destination d = new Destination(); - d.fromBase64(destKey); - _state.getPlotConfig().getClientConfig().setPeer(d); - _log.debug("Setting the peer to " + d.calculateHash().toBase64()); - } catch (DataFormatException dfe) { - _log.error("Unable to parse the peerDest line: [" + line + "]", dfe); - } - } - - private void handleLocalDest(String line) { - StringTokenizer tok = new StringTokenizer(line); - tok.nextToken(); // ignore; - String destKey = tok.nextToken(); - try { - Destination d = new Destination(); - d.fromBase64(destKey); - _state.getPlotConfig().getClientConfig().setUs(d); - } catch (DataFormatException dfe) { - _log.error("Unable to parse the localDest line: [" + line + "]", dfe); - } - } - - private void handleComment(String line) { - StringTokenizer tok = new StringTokenizer(line); - tok.nextToken(); // ignore; - StringBuffer buf = new StringBuffer(line.length()-32); - while (tok.hasMoreTokens()) - buf.append(tok.nextToken()).append(' '); - _state.getPlotConfig().getClientConfig().setComment(buf.toString()); - } - - private void handleNumTunnelHops(String line) { - StringTokenizer tok = new StringTokenizer(line); - tok.nextToken(); // ignore; - String num = tok.nextToken(); - try { - int val = Integer.parseInt(num); - _state.getPlotConfig().getClientConfig().setNumHops(val); - } catch (NumberFormatException nfe) { - _log.error("Unable to parse the numTunnelHops line: [" + line + "]", nfe); - } - } - - private void handleNumPending(String line) { - StringTokenizer tok = new StringTokenizer(line); - tok.nextToken(); // ignore; - String num = tok.nextToken(); - try { - int val = Integer.parseInt(num); - _state.getCurrentData().setPendingCount(val); - } catch (NumberFormatException nfe) { - _log.error("Unable to parse the numPending line: [" + line + "]", nfe); - } - } - - private void handleSendFrequency(String line) { - StringTokenizer tok = new StringTokenizer(line); - tok.nextToken(); // ignore; - String num = tok.nextToken(); - try { - int val = Integer.parseInt(num); - _state.getPlotConfig().getClientConfig().setSendFrequency(val); - } catch (NumberFormatException nfe) { - _log.error("Unable to parse the sendFrequency line: [" + line + "]", nfe); - } - } - - private void handleSendSize(String line) { - StringTokenizer tok = new StringTokenizer(line); - tok.nextToken(); // ignore; - String num = tok.nextToken(); - try { - int val = Integer.parseInt(num); - _state.getPlotConfig().getClientConfig().setSendSize(val); - } catch (NumberFormatException nfe) { - _log.error("Unable to parse the sendSize line: [" + line + "]", nfe); - } - } - - private void handleSessionStart(String line) { - StringTokenizer tok = new StringTokenizer(line); - tok.nextToken(); // ignore; - String date = tok.nextToken(); - try { - long when = getDate(date); - _state.getCurrentData().setSessionStart(when); - } catch (NumberFormatException nfe) { - _log.error("Unable to parse the sessionStart line: [" + line + "]", nfe); - } - } - - private void handlePeriodAverage(String line) { - StringTokenizer tok = new StringTokenizer(line); - tok.nextToken(); // ignore; - try { - // periodAverage minutes sendMs recvMs numLost - int min = Integer.parseInt(tok.nextToken()); - int send = Integer.parseInt(tok.nextToken()); - int recv = Integer.parseInt(tok.nextToken()); - int lost = Integer.parseInt(tok.nextToken()); - _state.addAverage(min, send, recv, lost); - } catch (NumberFormatException nfe) { - _log.error("Unable to parse the sendSize line: [" + line + "]", nfe); - } - } - - private void handleEvent(String line) { - StringTokenizer tok = new StringTokenizer(line); - - // * EVENT OK 20040409.23:29:21.288 701 661 - // * EVENT LOST 20040409.23:29:41.828 - tok.nextToken(); // ignore first two - tok.nextToken(); - try { - long when = getDate(tok.nextToken()); - if (when < 0) { - _log.error("Invalid EVENT line: [" + line + "]"); - return; - } - if (tok.hasMoreTokens()) { - int sendMs = Integer.parseInt(tok.nextToken()); - int recvMs = Integer.parseInt(tok.nextToken()); - _state.addSuccess(when, sendMs, recvMs); - } else { - _state.addLost(when); - } - } catch (NumberFormatException nfe) { - _log.error("Unable to parse the EVENT line: [" + line + "]", nfe); - } - } - - private static final SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd.HH:mm:ss.SSS", Locale.UK); - private long getDate(String date) { - synchronized (_fmt) { - try { - return _fmt.parse(date).getTime(); - } catch (ParseException pe) { - _log.error("Unable to parse the date [" + date + "]", pe); - return -1; - } - } - } - - private void fakeRun() { /* UNUSED */ - try { - Destination peer = new Destination(); - Destination us = new Destination(); - peer.fromBase64("3RPLOkQGlq8anNyNWhjbMyHxpAvUyUJKbiUejI80DnPR59T3blc7-XrBhQ2iPbf-BRAR~v1j34Kpba1eDyhPk2gevsE6ULO1irarJ3~C9WcQH2wAbNiVwfWqbh6onQ~YmkSpGNwGHD6ytwbvTyXeBJ" + - "cS8e6gmfNN-sYLn1aQu8UqWB3D6BmTfLtyS3eqWVk66Nrzmwy8E1Hvq5z~1lukYb~cyiDO1oZHAOLyUQtd9eN16yJY~2SRG8LiscpPMl9nSJUr6fmXMUubW-M7QGFH82Om-735PJUk6WMy1Hi9Vgh4Pxhdl7g" + - "fqGRWioFABdhcypb7p1Ca77p73uabLDFK-SjIYmdj7TwSdbNa6PCmzEvCEW~IZeZmnZC5B6pK30AdmD9vc641wUGce9xTJVfNRupf5L7pSsVIISix6FkKQk-FTW2RsZKLbuMCYMaPzLEx5gzODEqtI6Jf2teM" + - "d5xCz51RPayDJl~lJ-W0IWYfosnjM~KxYaqc4agviBuF5ZWeAAAA"); - us.fromBase64("W~JFpqSH8uopylox2V5hMbpcHSsb-dJkSKvdJ1vj~KQcUFJWXFyfbetBAukcGH5S559aK9oslU0qbVoMDlJITVC4OXfXSnVbJBP1IhsK8SvjSYicjmIi2fA~k4HvSh9Wxu~bg8yo~jgfHA8tjYpp" + - "K9QKc56BpkJb~hx0nNGy4Ny9eW~6A5AwAmHvwdt5NqcREYRMjRd63dMGm8BcEe-6FbOyMo3dnIFcETWAe8TCeoMxm~S1n~6Jlinw3ETxv-L6lQkhFFWnC5zyzQ~4JhVxxT3taTMYXg8td4CBGmrS078jcjW63" + - "rlSiQgZBlYfN3iEYmurhuIEV9NXRcmnMrBOQUAoXPpVuRIxJbaQNDL71FO2iv424n4YjKs84suAho34GGQKq7WoL5V5KQgihfcl0f~xne-qP3FtpoPFeyA9x-sA2JWDAsxoZlfvgkiP5eyOn23prT9TJK47HC" + - "VilHSV11uTVaC4Jc5YsjoBCZadWbgQnMCKlZ4jk-bLE1PSWLg7AAAA"); - _state.getPlotConfig().getClientConfig().setPeer(peer); - _state.getPlotConfig().getClientConfig().setUs(us); - _state.getPlotConfig().getClientConfig().setNumHops(2); - _state.getPlotConfig().getClientConfig().setComment("we do stuff\nreally nifty stuff. really"); - _state.getPlotConfig().getClientConfig().setAveragePeriods(new int[] { 1, 5, 30, 60 }); - int rnd = new java.util.Random().nextInt(); - if (rnd > 0) - rnd = rnd % 10; - else - rnd = (-rnd) % 10; - _state.getPlotConfig().getClientConfig().setSendFrequency(rnd); - _state.getPlotConfig().getClientConfig().setSendSize(16*1024); - _state.getPlotConfig().getClientConfig().setStatDuration(10); - _state.getPlotConfig().rebuildAverageSeriesConfigs(); - _state.setCurrentData(new StaticPeerData(_state.getPlotConfig().getClientConfig())); - - _receptor.peerPlotStateFetched(_state); - } catch (Exception e) { - e.printStackTrace(); - } - } - } -} \ No newline at end of file diff --git a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/StaticPeerData.java b/apps/heartbeat/java/src/net/i2p/heartbeat/gui/StaticPeerData.java deleted file mode 100644 index bcd20ca80..000000000 --- a/apps/heartbeat/java/src/net/i2p/heartbeat/gui/StaticPeerData.java +++ /dev/null @@ -1,134 +0,0 @@ -package net.i2p.heartbeat.gui; - -import java.util.HashMap; -import java.util.Map; - -import net.i2p.heartbeat.ClientConfig; -import net.i2p.heartbeat.PeerData; - -/** - * Raw data points for a test - */ -class StaticPeerData extends PeerData { - private int _pending; - /** Integer (period, in minutes) to Integer (milliseconds) for sending a ping */ - private Map _averageSendTimes; - /** Integer (period, in minutes) to Integer (milliseconds) for receiving a pong */ - private Map _averageReceiveTimes; - /** Integer (period, in minutes) to Integer (num messages) of how many messages were lost on average */ - private Map _lostMessages; - - /** - * Creates a static peer data with a specified client config ... duh - * @param config the client config - */ - public StaticPeerData(ClientConfig config) { - super(config); - _averageSendTimes = new HashMap(4); - _averageReceiveTimes = new HashMap(4); - _lostMessages = new HashMap(4); - } - - /** - * Adds averaged data - * @param minutes the minutes (averaged over) - * @param sendMs the send time (ping) in milliseconds - * @param recvMs the receive time (pong) in milliseconds - * @param lost the number lost - */ - public void addAverage(int minutes, int sendMs, int recvMs, int lost) { - _averageSendTimes.put(new Integer(minutes), new Integer(sendMs)); - _averageReceiveTimes.put(new Integer(minutes), new Integer(recvMs)); - _lostMessages.put(new Integer(minutes), new Integer(lost)); - } - - /** - * Sets the number pending - * @param numPending the number pending - */ - public void setPendingCount(int numPending) { _pending = numPending; } - - /* (non-Javadoc) - * @see net.i2p.heartbeat.PeerData#setSessionStart(long) - */ - public void setSessionStart(long when) { super.setSessionStart(when); } - - /** - * Adds data - * @param sendTime the time it was sent - * @param sendMs the send time (ping) in milliseconds - * @param recvMs the receive time (pong) in milliseconds - */ - public void addData(long sendTime, int sendMs, int recvMs) { - PeerData.EventDataPoint dataPoint = new PeerData.EventDataPoint(sendTime); - dataPoint.setPongSent(sendTime + sendMs); - dataPoint.setPongReceived(sendTime + sendMs + recvMs); - dataPoint.setWasPonged(true); - addDataPoint(dataPoint); - } - - /** - * Adds data - * @param sendTime the time it was sent - */ - public void addData(long sendTime) { - PeerData.EventDataPoint dataPoint = new PeerData.EventDataPoint(sendTime); - dataPoint.setWasPonged(false); - addDataPoint(dataPoint); - } - - /** - * how many pings are still outstanding? - * @return the number of pings outstanding - */ - public int getPendingCount() { return _pending; } - - - /** - * average time to send over the given period. - * - * @param period number of minutes to retrieve the average for - * @return milliseconds average, or -1 if we dont track that period - */ - public double getAverageSendTime(int period) { - Integer i = (Integer)_averageSendTimes.get(new Integer(period)); - if (i == null) - return -1; - - return i.doubleValue(); - } - - - /** - * average time to receive over the given period. - * - * @param period number of minutes to retrieve the average for - * @return milliseconds average, or -1 if we dont track that period - */ - public double getAverageReceiveTime(int period) { - Integer i = (Integer)_averageReceiveTimes.get(new Integer(period)); - if (i == null) - return -1; - - return i.doubleValue(); - } - - /** - * number of lost messages over the given period. - * - * @param period number of minutes to retrieve the average for - * @return number of lost messages in the period, or -1 if we dont track that period - */ - public double getLostMessages(int period) { - Integer i = (Integer)_lostMessages.get(new Integer(period)); - if (i == null) - return -1; - - return i.doubleValue(); - } - - /* (non-Javadoc) - * @see net.i2p.heartbeat.PeerData#cleanup() - */ - public void cleanup() {} -} \ No newline at end of file diff --git a/apps/httptunnel/doc/COPYING b/apps/httptunnel/doc/COPYING deleted file mode 100644 index 5ec43ee15..000000000 --- a/apps/httptunnel/doc/COPYING +++ /dev/null @@ -1,278 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. diff --git a/apps/httptunnel/doc/readme.license.txt b/apps/httptunnel/doc/readme.license.txt deleted file mode 100644 index 7f7c30bc7..000000000 --- a/apps/httptunnel/doc/readme.license.txt +++ /dev/null @@ -1,11 +0,0 @@ -$Id$ - -the i2p/apps/httptunnel module is the root of the -HTTPTunnel application, and everything within it -is released according to the terms of the I2P -license policy. That means everything contained -within the i2p/apps/httptunnel module is released -under the GPL plus the java exception unless -otherwise marked. Alternate licenses that may be -used include BSD, Cryptix, and MIT, as well as -code granted into the public domain. diff --git a/apps/httptunnel/java/build.xml b/apps/httptunnel/java/build.xml deleted file mode 100644 index 9dfe9ac58..000000000 --- a/apps/httptunnel/java/build.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPListener.java b/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPListener.java deleted file mode 100644 index 34ad8faa1..000000000 --- a/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPListener.java +++ /dev/null @@ -1,87 +0,0 @@ -package net.i2p.httptunnel; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; - -import net.i2p.util.Log; - -/** - * Listens on a port for HTTP connections. - */ -public class HTTPListener extends Thread { - - private static final Log _log = new Log(HTTPListener.class); - - private int port; - private String listenHost; - private SocketManagerProducer smp; - - /** - * A public constructor. It contstructs things. In this case, - * it constructs a nice HTTPListener, for all your listening on - * HTTP needs. Yep. That's right. - * @param smp A SocketManagerProducer, producing Sockets, no doubt - * @param port A port, to connect to. - * @param listenHost A host, to connect to. - */ - - public HTTPListener(SocketManagerProducer smp, int port, String listenHost) { - this.smp = smp; - this.port = port; - start(); - } - - /* (non-Javadoc) - * @see java.lang.Thread#run() - */ - public void run() { - try { - InetAddress lh = listenHost == null ? null : InetAddress.getByName(listenHost); - ServerSocket ss = new ServerSocket(port, 0, lh); - while (true) { - Socket s = ss.accept(); - new HTTPSocketHandler(this, s); - } - } catch (IOException ex) { - _log.error("Error while accepting connections", ex); - } - } - - private boolean proxyUsed = false; - - /** - * Query whether this is the first use of the proxy or not - * @return Whether this is the first proxy use, no doubt. - */ - public boolean firstProxyUse() { - if (true) return false; // FIXME: check a config option here - - if (proxyUsed) { - return false; - } - - proxyUsed = true; - return true; - } - - /** - * @return The SocketManagerProducer being used. - */ - public SocketManagerProducer getSMP() { - return smp; - } - - /** - * Outputs with HTTP 1.1 flair that a feature isn't implemented. - * @param out The stream the text goes to. - * @deprecated - * @throws IOException - */ - public void handleNotImplemented(OutputStream out) throws IOException { - out.write(("HTTP/1.1 200 Document following\n\n" + "

Feature not implemented

").getBytes("ISO-8859-1")); - out.flush(); - } -} \ No newline at end of file diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPSocketHandler.java b/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPSocketHandler.java deleted file mode 100644 index b5a15e019..000000000 --- a/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPSocketHandler.java +++ /dev/null @@ -1,62 +0,0 @@ -package net.i2p.httptunnel; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; - -import net.i2p.httptunnel.handler.RootHandler; -import net.i2p.util.Log; - -/** - * Handles a single HTTP socket connection. - */ -public class HTTPSocketHandler extends Thread { - - private static final Log _log = new Log(HTTPSocketHandler.class); - - private Socket s; - private HTTPListener httpl; - private RootHandler h; - - /** - * A public constructor. - * @param httpl An HTTPListener, to listen for HTTP, no doubt - * @param s A socket. - */ - public HTTPSocketHandler(HTTPListener httpl, Socket s) { - this.httpl = httpl; - this.s = s; - h = RootHandler.getInstance(); - start(); - } - - /* (non-Javadoc) - * @see java.lang.Thread#run() - */ - public void run() { - InputStream in = null; - OutputStream out = null; - try { - in = new BufferedInputStream(s.getInputStream()); - out = new BufferedOutputStream(s.getOutputStream()); - Request req = new Request(in); - h.handle(req, httpl, out); - } catch (IOException ex) { - _log.error("Error while handling data", ex); - } finally { - try { - if (in != null) in.close(); - if (out != null) { - out.flush(); - out.close(); - } - s.close(); - } catch (IOException ex) { - _log.error("IOException in finalizer", ex); - } - } - } -} \ No newline at end of file diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPTunnel.java b/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPTunnel.java deleted file mode 100644 index 4ff9325f0..000000000 --- a/apps/httptunnel/java/src/net/i2p/httptunnel/HTTPTunnel.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * HTTPTunnel - * (c) 2003 - 2004 mihi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * In addition, as a special exception, mihi gives permission to link - * the code of this program with the proprietary Java implementation - * provided by Sun (or other vendors as well), and distribute linked - * combinations including the two. You must obey the GNU General - * Public License in all respects for all of the code used other than - * the proprietary Java implementation. If you modify this file, you - * may extend this exception to your version of the file, but you are - * not obligated to do so. If you do not wish to do so, delete this - * exception statement from your version. - */ -package net.i2p.httptunnel; - -import net.i2p.client.streaming.I2PSocketManager; - -/** - * HTTPTunnel main class. - */ -public class HTTPTunnel { - - /** - * Create a HTTPTunnel instance. - * - * @param initialManagers a list of socket managers to use - * @param maxManagers how many managers to have in the cache - * @param shouldThrowAwayManagers whether to throw away a manager after use - * @param listenPort which port to listen on - */ - public HTTPTunnel(I2PSocketManager[] initialManagers, int maxManagers, boolean shouldThrowAwayManagers, - int listenPort) { - this(initialManagers, maxManagers, shouldThrowAwayManagers, listenPort, "127.0.0.1", 7654); - } - - /** - * Create a HTTPTunnel instance. - * - * @param initialManagers a list of socket managers to use - * @param maxManagers how many managers to have in the cache - * @param shouldThrowAwayManagers whether to throw away a manager after use - * @param listenPort which port to listen on - * @param i2cpAddress the I2CP address - * @param i2cpPort the I2CP port - */ - public HTTPTunnel(I2PSocketManager[] initialManagers, int maxManagers, boolean shouldThrowAwayManagers, - int listenPort, String i2cpAddress, int i2cpPort) { - SocketManagerProducer smp = new SocketManagerProducer(initialManagers, maxManagers, shouldThrowAwayManagers, - i2cpAddress, i2cpPort); - new HTTPListener(smp, listenPort, "127.0.0.1"); - } - - /** - * The all important main function, allowing HTTPTunnel to be - * stand-alone, a program in it's own right, and all that jazz. - * @param args A list of String passed to the program - */ - public static void main(String[] args) { - String host = "127.0.0.1"; - int port = 7654, max = 1; - boolean throwAwayManagers = false; - if (args.length > 1) { - if (args.length == 4) { - host = args[2]; - port = Integer.parseInt(args[3]); - } else if (args.length != 2) { - showInfo(); - return; - } - max = Integer.parseInt(args[1]); - } else if (args.length != 1) { - showInfo(); - return; - } - if (max == 0) { - max = 1; - } else if (max < 0) { - max = -max; - throwAwayManagers = true; - } - new HTTPTunnel(null, max, throwAwayManagers, Integer.parseInt(args[0]), host, port); - } - - private static void showInfo() { - System.out.println("Usage: java HTTPTunnel [ " + "[ ]]\n" - + " port to listen for browsers\n" - + " max number of SocketMangers in pool, " + "use neg. number\n" - + " to use each SocketManager only once " + "(default: 1)\n" - + " host to connect to the router " + "(default: 127.0.0.1)\n" - + " port to connect to the router " + "(default: 7654)"); - } -} \ No newline at end of file diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/Request.java b/apps/httptunnel/java/src/net/i2p/httptunnel/Request.java deleted file mode 100644 index b28aef795..000000000 --- a/apps/httptunnel/java/src/net/i2p/httptunnel/Request.java +++ /dev/null @@ -1,153 +0,0 @@ -package net.i2p.httptunnel; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringReader; - -import net.i2p.util.Log; - -/** - * A HTTP request (GET or POST). This will be passed to a hander for - * handling it. - */ -public class Request { - - private static final Log _log = new Log(Request.class); - - // all strings are forced to be ISO-8859-1 encoding - private String method; - private String url; - private String proto; - private String params; - private String postData; - - /** - * A constructor, creating a request from an InputStream - * @param in InputStream from which we "read-in" a Request - * @throws IOException - */ - public Request(InputStream in) throws IOException { - BufferedReader br = new BufferedReader(new InputStreamReader(in, "ISO-8859-1")); - String line = br.readLine(); - if (line == null) { // no data at all - method = null; - _log.error("Connection but no data"); - return; - } - int pos = line.indexOf(" "); - if (pos == -1) { - method = line; - url = ""; - _log.error("Malformed HTTP request: " + line); - } else { - method = line.substring(0, pos); - url = line.substring(pos + 1); - } - proto = ""; - pos = url.indexOf(" "); - if (pos != -1) { - proto = url.substring(pos); // leading space intended - url = url.substring(0, pos); - } - StringBuffer sb = new StringBuffer(512); - while ((line = br.readLine()) != null) { - if (line.length() == 0) break; - sb.append(line).append("\r\n"); - } - params = sb.toString(); // no leading empty line! - sb = new StringBuffer(); - // hack for POST requests, ripped from HttpClient - // this won't work for large POSTDATA - // FIXME: do this better, please. - if (!method.equals("GET")) { - while (br.ready()) { // empty the buffer (POST requests) - int i = br.read(); - if (i != -1) { - sb.append((char) i); - } - } - postData = sb.toString(); - } else { - postData = ""; - } - } - - /** - * @return A Request as an array of bytes of a String in ISO-8859-1 format - * @throws IOException - */ - public byte[] toByteArray() throws IOException { - if (method == null) return null; - return toISO8859_1String().getBytes("ISO-8859-1"); - - } - - private String toISO8859_1String() throws IOException { - if (method == null) return null; - return method + " " + url + proto + "\r\n" + params + "\r\n" + postData; - } - - /** - * @return the URL of the request - */ - public String getURL() { - return url; - } - - /** - * Sets the URL of the Request - * @param newURL the new URL - */ - public void setURL(String newURL) { - url = newURL; - } - - /** - * Retrieves the value of a param. - * @param name The name of the param - * @return The value of the param, or null - */ - public String getParam(String name) { - try { - BufferedReader br = new BufferedReader(new StringReader(params)); - String line; - while ((line = br.readLine()) != null) { - if (line.startsWith(name)) { return line.substring(name.length()); } - } - return null; - } catch (IOException ex) { - _log.error("Error getting parameter", ex); - return null; - } - } - - /** - * Sets the value of a param. - * @param name the name of the param - * @param value the value to be set - */ - public void setParam(String name, String value) { - try { - StringBuffer sb = new StringBuffer(params.length() + value.length()); - BufferedReader br = new BufferedReader(new StringReader(params)); - String line; - boolean replaced = false; - while ((line = br.readLine()) != null) { - if (line.startsWith(name)) { - replaced = true; - if (value == null) continue; // kill param - line = name + value; - } - sb.append(line).append("\r\n"); - } - if (!replaced && value != null) { - sb.append(name).append(value).append("\r\n"); - } - params = sb.toString(); - } catch (IOException ex) { - _log.error("Error getting parameter", ex); - } - } -} \ No newline at end of file diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/SocketManagerProducer.java b/apps/httptunnel/java/src/net/i2p/httptunnel/SocketManagerProducer.java deleted file mode 100644 index ddef387f8..000000000 --- a/apps/httptunnel/java/src/net/i2p/httptunnel/SocketManagerProducer.java +++ /dev/null @@ -1,120 +0,0 @@ -package net.i2p.httptunnel; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Properties; - -import net.i2p.client.streaming.I2PSocketManager; -import net.i2p.client.streaming.I2PSocketManagerFactory; - -/** - * Produces SocketManagers in a thread and gives them to those who - * need them. - */ -public class SocketManagerProducer extends Thread { - - private ArrayList myManagers = new ArrayList(); - private HashMap usedManagers = new HashMap(); - private int port; - private String host; - private int maxManagers; - private boolean shouldThrowAwayManagers; - - /** - * Public constructor creating a SocketManagerProducer - * @param initialManagers a list of socket managers to use - * @param maxManagers how many managers to have in the cache - * @param shouldThrowAwayManagers whether to throw away a manager after use - * @param host which host to listen on - * @param port which port to listen on - */ - public SocketManagerProducer(I2PSocketManager[] initialManagers, int maxManagers, boolean shouldThrowAwayManagers, - String host, int port) { - if (maxManagers < 1) { throw new IllegalArgumentException("maxManagers < 1"); } - this.host = host; - this.port = port; - this.shouldThrowAwayManagers = shouldThrowAwayManagers; - if (initialManagers != null) { - myManagers.addAll(Arrays.asList(initialManagers)); - } - this.maxManagers = maxManagers; - this.shouldThrowAwayManagers = shouldThrowAwayManagers; - setDaemon(true); - start(); - } - - /** - * Thread producing new SocketManagers. - */ - public void run() { - while (true) { - synchronized (this) { - // without mcDonalds mode, we most probably need no - // new managers. - while (!shouldThrowAwayManagers && myManagers.size() == maxManagers) { - myWait(); - } - } - // produce a new manager, regardless whether it is needed - // or not. Do not synchronized this part, since it can be - // quite time-consuming. - I2PSocketManager newManager = I2PSocketManagerFactory.createManager(host, port, new Properties()); - // when done, check if it is needed. - synchronized (this) { - while (myManagers.size() == maxManagers) { - myWait(); - } - myManagers.add(newManager); - notifyAll(); - } - } - } - - /** - * Get a manager for connecting to a given destination. Each - * destination will always get the same manager. - * - * @param dest the destination to connect to - * @return the SocketManager to use - */ - public synchronized I2PSocketManager getManager(String dest) { - I2PSocketManager result = (I2PSocketManager) usedManagers.get(dest); - if (result == null) { - result = getManager(); - usedManagers.put(dest, result); - } - return result; - } - - /** - * Get a "new" SocketManager. Depending on the anonymity settings, - * this can be a completely new one or one randomly selected from - * a pool. - * - * @return the SocketManager to use - */ - public synchronized I2PSocketManager getManager() { - while (myManagers.size() == 0) { - myWait(); // no manager here, so wait until one is produced - } - int which = (int) (Math.random() * myManagers.size()); - I2PSocketManager result = (I2PSocketManager) myManagers.get(which); - if (shouldThrowAwayManagers) { - myManagers.remove(which); - notifyAll(); - } - return result; - } - - /** - * Wait until InterruptedException - */ - public void myWait() { - try { - wait(); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } - } -} \ No newline at end of file diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/filter/ChainFilter.java b/apps/httptunnel/java/src/net/i2p/httptunnel/filter/ChainFilter.java deleted file mode 100644 index b71a19469..000000000 --- a/apps/httptunnel/java/src/net/i2p/httptunnel/filter/ChainFilter.java +++ /dev/null @@ -1,61 +0,0 @@ -package net.i2p.httptunnel.filter; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Collection; -import java.util.Iterator; - -import net.i2p.util.Log; - -/** - * Chain multiple filters. Decorator pattern... - */ -public class ChainFilter implements Filter { - - private static final Log _log = new Log(ChainFilter.class); - - private Collection filters; // perhaps protected? - - /** - * @param filters A collection (list) of filters to chain to - */ - public ChainFilter(Collection filters) { - this.filters = filters; - } - - /* (non-Javadoc) - * @see net.i2p.httptunnel.filter.Filter#filter(byte[]) - */ - public byte[] filter(byte[] toFilter) { - byte[] buf = toFilter; - for (Iterator it = filters.iterator(); it.hasNext();) { - Filter f = (Filter) it.next(); - buf = f.filter(buf); - } - return buf; - } - - /* (non-Javadoc) - * @see net.i2p.httptunnel.filter.Filter#finish() - */ - public byte[] finish() { - // this is a bit complicated. Think about it... - try { - byte[] buf = EMPTY; - for (Iterator it = filters.iterator(); it.hasNext();) { - Filter f = (Filter) it.next(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - if (buf.length != 0) { - baos.write(f.filter(buf)); - } - baos.write(f.finish()); - buf = baos.toByteArray(); - } - return buf; - } catch (IOException ex) { - _log.error("Error chaining filters", ex); - return EMPTY; - } - } - -} \ No newline at end of file diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/filter/Filter.java b/apps/httptunnel/java/src/net/i2p/httptunnel/filter/Filter.java deleted file mode 100644 index d0ba2b6ff..000000000 --- a/apps/httptunnel/java/src/net/i2p/httptunnel/filter/Filter.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.i2p.httptunnel.filter; - -/** - * A generic filtering interface. - */ -public interface Filter { - - /** - * An empty byte array. - */ - public static final byte[] EMPTY = new byte[0]; - - /** - * Filter some data. Not all filtered data need to be returned. - * @param toFilter the bytes that are to be filtered. - * @return the filtered data - */ - public byte[] filter(byte[] toFilter); - - /** - * Data stream has finished. Return all of the rest data. - * @return the rest of the data - */ - public byte[] finish(); -} \ No newline at end of file diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/filter/NullFilter.java b/apps/httptunnel/java/src/net/i2p/httptunnel/filter/NullFilter.java deleted file mode 100644 index a609ba5f2..000000000 --- a/apps/httptunnel/java/src/net/i2p/httptunnel/filter/NullFilter.java +++ /dev/null @@ -1,21 +0,0 @@ -package net.i2p.httptunnel.filter; - -/** - * A filter letting everything pass as is. - */ -public class NullFilter implements Filter { - - /* (non-Javadoc) - * @see net.i2p.httptunnel.filter.Filter#filter(byte[]) - */ - public byte[] filter(byte[] toFilter) { - return toFilter; - } - - /* (non-Javadoc) - * @see net.i2p.httptunnel.filter.Filter#finish() - */ - public byte[] finish() { - return EMPTY; - } -} \ No newline at end of file diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/EepHandler.java b/apps/httptunnel/java/src/net/i2p/httptunnel/handler/EepHandler.java deleted file mode 100644 index 4e9ffb367..000000000 --- a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/EepHandler.java +++ /dev/null @@ -1,113 +0,0 @@ -package net.i2p.httptunnel.handler; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.SocketException; - -import net.i2p.I2PAppContext; -import net.i2p.I2PException; -import net.i2p.client.streaming.I2PSocket; -import net.i2p.client.streaming.I2PSocketManager; -import net.i2p.client.streaming.I2PSocketOptions; -import net.i2p.data.Destination; -import net.i2p.httptunnel.HTTPListener; -import net.i2p.httptunnel.Request; -import net.i2p.httptunnel.SocketManagerProducer; -import net.i2p.httptunnel.filter.Filter; -import net.i2p.httptunnel.filter.NullFilter; -import net.i2p.util.Log; - -/** - * Handler for browsing Eepsites. - */ -public class EepHandler { - - private static final Log _log = new Log(EepHandler.class); - private static I2PAppContext _context = new I2PAppContext(); - - protected ErrorHandler errorHandler; - - /* package private */EepHandler(ErrorHandler eh) { - errorHandler = eh; - } - - /** - * @param req the Request - * @param httpl an HTTPListener - * @param out where to write the results - * @param destination destination as a string, (subject to naming - * service lookup) - * @throws IOException - */ - public void handle(Request req, HTTPListener httpl, OutputStream out, - /* boolean fromProxy, */String destination) throws IOException { - SocketManagerProducer smp = httpl.getSMP(); - Destination dest = _context.namingService().lookup(destination); - if (dest == null) { - errorHandler.handle(req, httpl, out, "Could not lookup host: " + destination); - return; - } - I2PSocketManager sm = smp.getManager(destination); - Filter f = new NullFilter(); //FIXME: use other filter - req.setParam("Host: ", dest.toBase64()); - if (!handle(req, f, out, dest, sm)) { - errorHandler.handle(req, httpl, out, "Unable to reach peer"); - } - } - - /** - * @param req the Request to send out - * @param f a Filter to apply to the bytes retrieved from the Destination - * @param out where to write the results - * @param dest the Destination of the Request - * @param sm an I2PSocketManager, to get a socket for the Destination - * @return boolean, true if something was written, false otherwise. - * @throws IOException - */ - public boolean handle(Request req, Filter f, OutputStream out, Destination dest, - I2PSocketManager sm) throws IOException { - I2PSocket s = null; - boolean written = false; - try { - synchronized (sm) { - s = sm.connect(dest, new I2PSocketOptions()); - } - InputStream in = new BufferedInputStream(s.getInputStream()); - OutputStream sout = new BufferedOutputStream(s.getOutputStream()); - sout.write(req.toByteArray()); - sout.flush(); - byte[] buffer = new byte[16384], filtered; - int len; - while ((len = in.read(buffer)) != -1) { - if (len != buffer.length) { - byte[] b2 = new byte[len]; - System.arraycopy(buffer, 0, b2, 0, len); - filtered = f.filter(b2); - } else { - filtered = f.filter(buffer); - } - written = true; - out.write(filtered); - } - filtered = f.finish(); - written = true; - out.write(filtered); - out.flush(); - } catch (SocketException ex) { - _log.error("Error while handling eepsite request"); - return written; - } catch (IOException ex) { - _log.error("Error while handling eepsite request"); - return written; - } catch (I2PException ex) { - _log.error("Error while handling eepsite request"); - return written; - } finally { - if (s != null) s.close(); - } - return true; - } -} diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/ErrorHandler.java b/apps/httptunnel/java/src/net/i2p/httptunnel/handler/ErrorHandler.java deleted file mode 100644 index 35c296281..000000000 --- a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/ErrorHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -package net.i2p.httptunnel.handler; - -import java.io.IOException; -import java.io.OutputStream; - -import net.i2p.httptunnel.HTTPListener; -import net.i2p.httptunnel.Request; -import net.i2p.util.Log; - -/** - * Handler for general error messages. - */ -public class ErrorHandler { - - private static final Log _log = new Log(ErrorHandler.class); /* UNUSED */ - - /* package private */ErrorHandler() { - - } - - /** - * @param req the Request - * @param httpl an HTTPListener - * @param out where to write the results - * @param error the error that happened - * @throws IOException - */ - public void handle(Request req, HTTPListener httpl, OutputStream out, String error) throws IOException { - // FIXME: Make nicer messages for more likely errors. - out - .write(("HTTP/1.1 500 Internal Server Error\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n\r\n") - .getBytes("ISO-8859-1")); - out - .write(("" + error + "

" + error - + "

An internal error occurred while " + "handling a request by HTTPTunnel:
" + error + "

Complete request:

---
\r\n")
-                                                                                                                                                                                .getBytes("ISO-8859-1"));
-        out.write(req.toByteArray());
-        out.write(("

---").getBytes("ISO-8859-1")); - out.flush(); - } -} \ No newline at end of file diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/LocalHandler.java b/apps/httptunnel/java/src/net/i2p/httptunnel/handler/LocalHandler.java deleted file mode 100644 index b2142c610..000000000 --- a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/LocalHandler.java +++ /dev/null @@ -1,67 +0,0 @@ -package net.i2p.httptunnel.handler; - -import java.io.IOException; -import java.io.OutputStream; - -import net.i2p.httptunnel.HTTPListener; -import net.i2p.httptunnel.Request; -import net.i2p.util.Log; - -/** - * Handler for requests that do not require any connection to anyone - * (except errors). - */ -public class LocalHandler { - - private static final Log _log = new Log(LocalHandler.class); /* UNUSED */ - - /* package private */LocalHandler() { - } - - /** - * @param req the Request - * @param httpl an HTTPListener - * @param out where to write the results - * @throws IOException - */ - public void handle(Request req, HTTPListener httpl, OutputStream out - /*, boolean fromProxy */) throws IOException { - //FIXME: separate multiple pages, not only a start page - //FIXME: provide some info on this page - out - .write(("HTTP/1.1 200 Document following\r\n" + "Content-Type: text/html; charset=iso-8859-1\r\n\r\n" - + "Welcome to I2P HTTPTunnel" - + "

Welcome to I2P HTTPTunnel

You can " - + "browse Eepsites by adding an eepsite name to the request." + "") - .getBytes("ISO-8859-1")); - out.flush(); - } - - /** - * Currently always throws an IO Exception - * @param req the Request - * @param httpl an HTTPListener - * @param out where to write the results - * @throws IOException - */ - public void handleProxyConfWarning(Request req, HTTPListener httpl, OutputStream out) throws IOException { - //FIXME - throw new IOException("jrandom ate the deprecated method. mooo"); - //httpl.handleNotImplemented(out); - - } - - /** - * Currently always throws an IO Exception - * @param req the Request - * @param httpl an HTTPListener - * @param out where to write the results - * @throws IOException - */ - public void handleHTTPWarning(Request req, HTTPListener httpl, OutputStream out /*, boolean fromProxy */) - throws IOException { - // FIXME - throw new IOException("jrandom ate the deprecated method. mooo"); - //httpl.handleNotImplemented(out); - } -} \ No newline at end of file diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/ProxyHandler.java b/apps/httptunnel/java/src/net/i2p/httptunnel/handler/ProxyHandler.java deleted file mode 100644 index a0e55e931..000000000 --- a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/ProxyHandler.java +++ /dev/null @@ -1,54 +0,0 @@ -package net.i2p.httptunnel.handler; - -import java.io.IOException; -import java.io.OutputStream; - -import net.i2p.I2PAppContext; -import net.i2p.client.streaming.I2PSocketManager; -import net.i2p.data.Destination; -import net.i2p.httptunnel.HTTPListener; -import net.i2p.httptunnel.Request; -import net.i2p.httptunnel.SocketManagerProducer; -import net.i2p.httptunnel.filter.Filter; -import net.i2p.httptunnel.filter.NullFilter; -import net.i2p.util.Log; - -/** - * Handler for proxying "normal" HTTP requests. - */ -public class ProxyHandler extends EepHandler { - - private static final Log _log = new Log(ErrorHandler.class); /* UNUSED */ - private static I2PAppContext _context = new I2PAppContext(); - - /* package private */ProxyHandler(ErrorHandler eh) { - super(eh); - } - - /** - * @param req a Request - * @param httpl an HTTPListener - * @param out where to write the results - * @throws IOException - */ - public void handle(Request req, HTTPListener httpl, OutputStream out - /*, boolean fromProxy */) throws IOException { - SocketManagerProducer smp = httpl.getSMP(); - Destination dest = findProxy(); - if (dest == null) { - errorHandler.handle(req, httpl, out, "Could not find proxy"); - return; - } - // one manager for all proxy requests - I2PSocketManager sm = smp.getManager("--proxy--"); - Filter f = new NullFilter(); //FIXME: use other filter - if (!handle(req, f, out, dest, sm)) { - errorHandler.handle(req, httpl, out, "Unable to reach peer"); - } - } - - private Destination findProxy() { - //FIXME! - return _context.namingService().lookup("squid.i2p"); - } -} \ No newline at end of file diff --git a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/RootHandler.java b/apps/httptunnel/java/src/net/i2p/httptunnel/handler/RootHandler.java deleted file mode 100644 index 1cb0b2694..000000000 --- a/apps/httptunnel/java/src/net/i2p/httptunnel/handler/RootHandler.java +++ /dev/null @@ -1,116 +0,0 @@ -package net.i2p.httptunnel.handler; - -import java.io.IOException; -import java.io.OutputStream; - -import net.i2p.httptunnel.HTTPListener; -import net.i2p.httptunnel.Request; -import net.i2p.util.Log; - -/** - * Main handler for all requests. Dispatches requests to other handlers. - */ -public class RootHandler { - - private static final Log _log = new Log(RootHandler.class); /* UNUSED */ - - private RootHandler() { - errorHandler = new ErrorHandler(); - localHandler = new LocalHandler(); - proxyHandler = new ProxyHandler(errorHandler); - eepHandler = new EepHandler(errorHandler); - } - - private ErrorHandler errorHandler; - private ProxyHandler proxyHandler; - private LocalHandler localHandler; - private EepHandler eepHandler; - - private static RootHandler instance; - - /** - * Singleton stuff - * @return the one and only instance, yay! - */ - public static synchronized RootHandler getInstance() { - if (instance == null) { - instance = new RootHandler(); - } - return instance; - } - - /** - * The _ROOT_ handler: it passes its workload off to the other handlers. - * @param req a Request - * @param httpl an HTTPListener - * @param out where to write the results - * @throws IOException - */ - public void handle(Request req, HTTPListener httpl, OutputStream out) throws IOException { - String url = req.getURL(); - System.out.println(url); - /* boolean byProxy = false; */ - int pos; - if (url.startsWith("http://")) { // access via proxy - /* byProxy=true; */ - if (httpl.firstProxyUse()) { - localHandler.handleProxyConfWarning(req, httpl, out); - return; - } - url = url.substring(7); - pos = url.indexOf("/"); - String host; - - if (pos == -1) { - errorHandler.handle(req, httpl, out, "No host end in URL"); - return; - } - - host = url.substring(0, pos); - url = url.substring(pos); - if ("i2p".equals(host) || "i2p.i2p".equals(host)) { - // normal request; go on below... - } else if (host.endsWith(".i2p")) { - // "old" service request, send a redirect... - out.write(("HTTP/1.1 302 Moved\r\nLocation: " + "http://i2p.i2p/" + host + url + "\r\n\r\n").getBytes("ISO-8859-1")); - return; - } else { - // this is for proxying to the real web - proxyHandler.handle(req, httpl, out /*, true */); - return; - } - } - if (url.equals("/")) { // main page - url = "/_/local/index"; - } else if (!url.startsWith("/")) { - errorHandler.handle(req, httpl, out, "No leading slash in URL: " + url); - return; - } - String dest; - url = url.substring(1); - pos = url.indexOf("/"); - if (pos == -1) { - dest = url; - url = "/"; - } else { - dest = url.substring(0, pos); - url = url.substring(pos); - } - req.setURL(url); - if (dest.equals("_")) { // no eepsite - if (url.startsWith("/local/")) { // local request - req.setURL(url.substring(6)); - localHandler.handle(req, httpl, out /*, byProxy */); - } else if (url.startsWith("/http/")) { // http warning - localHandler.handleHTTPWarning(req, httpl, out /*, byProxy */); - } else if (url.startsWith("/proxy/")) { // http proxying - req.setURL("http://" + url.substring(7)); - proxyHandler.handle(req, httpl, out /*, byProxy */); - } else { - errorHandler.handle(req, httpl, out, "No local handler for this URL: " + url); - } - } else { - eepHandler.handle(req, httpl, out, /* byProxy, */dest); - } - } -} \ No newline at end of file diff --git a/apps/jfreechart/GUI-licenses.txt b/apps/jfreechart/GUI-licenses.txt deleted file mode 100644 index dcbe66d02..000000000 --- a/apps/jfreechart/GUI-licenses.txt +++ /dev/null @@ -1,590 +0,0 @@ -The code for the GUI applications netviewer and the -heartbeat GUI have been released into the public domain, -but they make use of the LGPL JFreeChart library (which -in turn depends upon the APL log4j library). These -external components, contained within the files: - lib/jfreechart-0.9.17.jar - lib/jcommon-0.9.2.jar - lib/log4j-1.2.8.jar -were retrieved and built from the source at -http://www.jfree.org/jfreechart/jfreechart-0.9.17.zip - -As a whole, the netviewer and heartbeat GUI applications -therefore must state: - This product includes software developed by the - Apache Software Foundation (http://www.apache.org/). - -The LGPL just makes us state prominently that we use LGPL'ed -code (the JFreeChart code), and since we make no modifications -to it, section 6.b of the LGPL seems to apply. - -The relevent licenses are shown below. - -***************************************************************** -For the jfreechart-0.9.17.jar and jcommon-0.9.2.jar, the -LGPL is relevent: -***************************************************************** - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - -***************************************************************** -For the file log4j-1.2.8.jar, the APL is relevent: -***************************************************************** -/* ==================================================================== - * - * The Apache Software License, Version 1.1 - * - * Copyright (c) 2003 The Apache Software Foundation. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, if - * any, must include the following acknowlegement: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowlegement may appear in the software itself, - * if and wherever such third-party acknowlegements normally appear. - * - * 4. The names "The Apache Logging Services Project", "log4j", and "Apache Software - * Foundation" must not be used to endorse or promote products derived - * from this software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache" - * nor may "Apache" appear in their names without prior written - * permission of the Apache Group. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * . - * - * [Additional notices, if required by prior licensing conditions] - * - */ diff --git a/apps/jfreechart/build.xml b/apps/jfreechart/build.xml deleted file mode 100644 index 91434d611..000000000 --- a/apps/jfreechart/build.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/myi2p/java/build.xml b/apps/myi2p/java/build.xml deleted file mode 100644 index 6c79ddc73..000000000 --- a/apps/myi2p/java/build.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/myi2p/java/src/net/i2p/myi2p/MyI2PMessage.java b/apps/myi2p/java/src/net/i2p/myi2p/MyI2PMessage.java deleted file mode 100644 index e2b05666d..000000000 --- a/apps/myi2p/java/src/net/i2p/myi2p/MyI2PMessage.java +++ /dev/null @@ -1,116 +0,0 @@ -package net.i2p.myi2p; - -import net.i2p.data.Destination; - -/** - * Packages up a message for delivery. The raw format of the message within a - * repliable datagram is - * MyI2P $maj.$min $service $type\n$payload - * where $maj.$min is currently 1.0, $service is the type of MyI2P - * service, $type is the type of message within that service, and $payload is - * the data specific to that type. - * - */ -public class MyI2PMessage { - private Destination _peer; - private String _service; - private String _type; - private byte[] _payload; - - private static final byte[] MESSAGE_PREFIX = "MyI2P 1.0 ".getBytes(); - - /** - * Build a new MyI2P message to be sent. - * - * @param to address to send the message - * @param service what MyI2P service is involved - * @param type type of message within that service is involved - * @param data payload of the message to deliver - */ - public MyI2PMessage(Destination to, String service, String type, byte data[]) { - _peer = to; - _service = service; - _type = type; - _payload = data; - } - - /** - * Read in the MyI2P data from the given datagram info. - * - * @param from authenticated from address - * @param dgramPayload raw MyI2P formatted message - * @throws IllegalArgumentException if the message is not a valid MyI2P message - */ - public MyI2PMessage(Destination from, byte dgramPayload[]) throws IllegalArgumentException { - _peer = from; - int index = 0; - while (index < dgramPayload.length) { - if (index >= MESSAGE_PREFIX.length) break; - if (dgramPayload[index] != MESSAGE_PREFIX[index]) - throw new IllegalArgumentException("Invalid payload (not a MyI2P message)"); - index++; - } - - // $service $type\n$payload - StringBuffer service = new StringBuffer(8); - while (index < dgramPayload.length) { - if (dgramPayload[index] == ' ') { - _service = service.toString(); - index++; - break; - } else if (dgramPayload[index] == '\n') { - throw new IllegalArgumentException("Ran into newline while reading the service"); - } else { - service.append((char)dgramPayload[index]); - index++; - } - } - - StringBuffer type = new StringBuffer(8); - while (index < dgramPayload.length) { - if (dgramPayload[index] == '\n') { - _type = type.toString(); - index++; - break; - } else { - service.append((char)dgramPayload[index]); - index++; - } - } - - _payload = new byte[dgramPayload.length-index]; - System.arraycopy(dgramPayload, index, _payload, 0, _payload.length); - } - - /** who is this message from or who is it going to? */ - public Destination getPeer() { return _peer; } - /** what MyI2P service is this bound for (addressBook, blog, etc)? */ - public String getServiceType() { return _service; } - /** within that service, what type of message is this? */ - public String getMessageType() { return _type; } - /** what is the raw data for the particular message? */ - public byte[] getPayload() { return _payload; } - - /** - * Retrieve the raw payload, suitable for wrapping in an I2PDatagramMaker - * and sending to another MyI2P node. - * - * @throws IllegalStateException if some data is missing - */ - public byte[] toRawPayload() throws IllegalStateException { - if (_service == null) throw new IllegalStateException("Service is null"); - if (_type == null) throw new IllegalStateException("Type is null"); - if (_payload == null) throw new IllegalStateException("Payload is null"); - - byte service[] = _service.getBytes(); - byte type[] = _type.getBytes(); - byte rv[] = new byte[MESSAGE_PREFIX.length + service.length + 1 + type.length + 1 + _payload.length]; - System.arraycopy(MESSAGE_PREFIX, 0, rv, 0, MESSAGE_PREFIX.length); - System.arraycopy(service, 0, rv, MESSAGE_PREFIX.length, service.length); - rv[MESSAGE_PREFIX.length + service.length] = ' '; - System.arraycopy(type, 0, rv, MESSAGE_PREFIX.length + service.length + 1, type.length); - rv[MESSAGE_PREFIX.length + service.length + 1 + type.length] = '\n'; - System.arraycopy(_payload, 0, rv, MESSAGE_PREFIX.length + service.length + 1 + type.length + 1, _payload.length); - return rv; - } -} diff --git a/apps/myi2p/java/src/net/i2p/myi2p/Node.java b/apps/myi2p/java/src/net/i2p/myi2p/Node.java deleted file mode 100644 index 71845f31e..000000000 --- a/apps/myi2p/java/src/net/i2p/myi2p/Node.java +++ /dev/null @@ -1,266 +0,0 @@ -package net.i2p.myi2p; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import net.i2p.I2PAppContext; -import net.i2p.util.Log; - -/** - * Main controller for a MyI2P node, coordinating all network communication and - * distributing messages to the appropriate services. - * - */ -public class Node { - private static List _nodes = new ArrayList(1); - /** - * Return a list of Node instances that are currently - * operating in the JVM - */ - private static List nodes() { - synchronized (_nodes) { - return new ArrayList(_nodes); - } - } - - private I2PAppContext _context; - private Log _log; - private NodeAdapter _adapter; - /** - * contains configuration properties, such where our router is, what - * services to run, etc - * - */ - private Properties _config; - /** filename where _config is stored */ - private String _configFile = DEFAULT_CONFIG_FILE; - /** mapping of service name (String) to Service for all services loaded */ - private Map _services; - - private static final String DEFAULT_CONFIG_FILE = "myi2p.config"; - private static final String DEFAULT_KEY_FILE = "myi2p.keys"; - private static final String PROP_KEY_FILE = "keyFile"; - - public Node(I2PAppContext context) { - _context = context; - _log = context.logManager().getLog(Node.class); - _config = new Properties(); - _services = new HashMap(1); - if (_log.shouldLog(Log.CRIT)) - _log.log(Log.CRIT, "Node created"); - _adapter = new NodeAdapter(_context, this); - } - - /** - * Main driver for the node. Usage: Node [configFile] - * - */ - public static void main(String args[]) { - String filename = DEFAULT_CONFIG_FILE; - if ( (args != null) && (args.length == 1) ) - filename = args[0]; - Node node = new Node(I2PAppContext.getGlobalContext()); - node.setConfigFile(filename); - node.loadConfig(); - node.startup(); - while (true) { - //try { Thread.sleep(10*1000); } catch (InterruptedException ie) {} - //node.shutdown(); - //if (true) return; - synchronized (node) { - try { node.wait(); } catch (InterruptedException ie) {} - } - } - } - - public Properties getConfig() { - synchronized (_config) { - return new Properties(_config); - } - } - public void setConfig(Properties props) { - synchronized (_config) { - _config.clear(); - _config.putAll(props); - } - } - - public String getConfigFile() { return _configFile; } - public void setConfigFile(String filename) { _configFile = filename; } - - /** - * Load up the config and all of the services - * - */ - public void loadConfig() { - FileInputStream fis = null; - try { - File cfgFile = new File(_configFile); - if (cfgFile.exists()) { - fis = new FileInputStream(cfgFile); - Properties props = new Properties(); - props.load(fis); - setConfig(props); - if (_log.shouldLog(Log.INFO)) - _log.info("Config loaded from " + _configFile); - } else { - if (_log.shouldLog(Log.ERROR)) - _log.error("Config file " + _configFile + " does not exist, so we aren't going to do much"); - } - } catch (IOException ioe) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Error reading config file " + _configFile, ioe); - } finally { - if (fis != null) try { fis.close(); } catch (IOException ioe) {} - } - } - - /** - * Boot up the node, connect to the router, and start all the services - * - */ - public void startup() { - boolean connected = connect(); - if (connected) { - Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { - public void run() { shutdown(); } - })); - loadServices(); - startServices(); - synchronized (_nodes) { - _nodes.add(this); - } - if (_log.shouldLog(Log.INFO)) - _log.info("Node started"); - } else { - if (_log.shouldLog(Log.ERROR)) - _log.error("Unable to connect, startup didn't do much"); - } - } - - /** - * Drop any connections to the network and stop all services - * - */ - public void shutdown() { - disconnect(); - stopServices(); - synchronized (_nodes) { - _nodes.remove(this); - } - } - - /** - * Send a message from the node to the peer as specified in the message - * - * @return true if it was sent - */ - public boolean sendMessage(MyI2PMessage msg) { - return _adapter.sendMessage(msg); - } - - private void loadServices() { - Properties config = getConfig(); - int i = 0; - while (true) { - String classname = config.getProperty("service."+i+".classname"); - if ( (classname == null) || (classname.trim().length() <= 0) ) - break; - boolean ok = loadService("service." + i + ".", config); - if (ok) i++; - } - if (_log.shouldLog(Log.INFO)) - _log.info(i + " services loaded"); - } - - private boolean loadService(String prefix, Properties config) { - String classname = config.getProperty(prefix + "classname"); - String type = config.getProperty(prefix + "type"); - if (type == null) return false; - - Properties opts = new Properties(); - int i = 0; - while (true) { - String name = config.getProperty(prefix + "option." + i + ".name"); - String value = config.getProperty(prefix + "option." + i + ".value"); - if ( (name == null) || (name.trim().length() <= 0) || (value == null) || (value.trim().length() <= 0) ) - break; - opts.setProperty(name.trim(), value.trim()); - i++; - } - - try { - Class cls = Class.forName(classname); - Object obj = cls.newInstance(); - if (obj instanceof Service) { - Service service = (Service)obj; - service.setType(type); - service.setOptions(opts); - service.setNode(this); - service.setContext(_context); - synchronized (_services) { - _services.put(type, service); - } - if (_log.shouldLog(Log.INFO)) - _log.info("Service " + type + " loaded"); - return true; - } else { - if (_log.shouldLog(Log.ERROR)) - _log.error("Error loading service " + type + ": not a service [" + classname + "]"); - } - } catch (ClassNotFoundException cnfe) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Error loading service " + type + ": class " + classname + " is invalid", cnfe); - } catch (InstantiationException ie) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Error instantiating service " + type + ": class " + classname + " could not be created", ie); - } catch (IllegalAccessException iae) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Error creating service " + type + ": class " + classname + " could not be accessed", iae); - } - return false; - } - - private boolean connect() { - Properties config = getConfig(); - File keyFile = new File(config.getProperty(PROP_KEY_FILE, DEFAULT_KEY_FILE)); - return _adapter.connect(config, keyFile); - } - - private void disconnect() { - _adapter.disconnect(); - } - - private void startServices() { - for (Iterator iter = _services.values().iterator(); iter.hasNext(); ) { - Service service = (Service)iter.next(); - service.startup(); - } - } - private void stopServices() { - for (Iterator iter = _services.values().iterator(); iter.hasNext(); ) { - Service service = (Service)iter.next(); - service.shutdown(); - } - } - - void handleMessage(MyI2PMessage msg) { - Service service = (Service)_services.get(msg.getServiceType()); - if (service == null) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Message received for an unknown service [" - + msg.getServiceType() + "] from " - + msg.getPeer().calculateHash().toBase64()); - } else { - service.receiveMessage(msg); - } - } -} diff --git a/apps/myi2p/java/src/net/i2p/myi2p/NodeAdapter.java b/apps/myi2p/java/src/net/i2p/myi2p/NodeAdapter.java deleted file mode 100644 index bfb5906ec..000000000 --- a/apps/myi2p/java/src/net/i2p/myi2p/NodeAdapter.java +++ /dev/null @@ -1,178 +0,0 @@ -package net.i2p.myi2p; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileInputStream; -import java.io.IOException; - -import java.util.Properties; - -import net.i2p.I2PAppContext; -import net.i2p.I2PException; -import net.i2p.client.I2PClient; -import net.i2p.client.I2PClientFactory; -import net.i2p.client.I2PSession; -import net.i2p.client.I2PSessionListener; -import net.i2p.client.I2PSessionException; -import net.i2p.client.datagram.I2PDatagramDissector; -import net.i2p.client.datagram.I2PDatagramMaker; -import net.i2p.client.datagram.I2PInvalidDatagramException; -import net.i2p.data.DataFormatException; -import net.i2p.data.Destination; -import net.i2p.util.Log; - -/** - * Bind the MyI2P node to the I2P network, handling messages, sessions, - * etc. - * - */ -public class NodeAdapter implements I2PSessionListener { - private I2PAppContext _context; - private Log _log; - private Node _node; - private I2PSession _session; - - public NodeAdapter(I2PAppContext context, Node node) { - _node = node; - _context = context; - _log = context.logManager().getLog(NodeAdapter.class); - } - - boolean sendMessage(MyI2PMessage msg) { - if (_session == null) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Cannot send the message, as we are not connected"); - return false; - } - try { - I2PDatagramMaker builder = new I2PDatagramMaker(_session); - byte dgram[] = builder.makeI2PDatagram(msg.toRawPayload()); - return _session.sendMessage(msg.getPeer(), dgram); - } catch (IllegalStateException ise) { - if (_log.shouldLog(Log.ERROR)) - _log.error("MyI2PMessage was not valid", ise); - return false; - } catch (I2PSessionException ise) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Error sending to the peer", ise); - return false; - } - } - - /** - * Connect to the network using the current I2CP config and the private - * key file specified in the node config. If the file does not exist, a new - * destination will be created. - * - * @param config MyI2P node and I2CP configuration - * @param keyFile file to load the private keystream from (if it doesn't - * exist, a new one will be created and stored at that location) - * - * @return true if connection was successful, false otherwise - */ - boolean connect(Properties config, File keyFile) { - I2PClient client = I2PClientFactory.createClient(); - if (!keyFile.exists()) { - File parent = keyFile.getParentFile(); - if (parent != null) parent.mkdirs(); - FileOutputStream fos = null; - try { - fos = new FileOutputStream(keyFile); - Destination dest = client.createDestination(fos); - if (_log.shouldLog(Log.INFO)) - _log.info("New destination created [" - + dest.calculateHash().toBase64() - + "] with keys at " + keyFile); - } catch (IOException ioe) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Error writing new keystream to " + keyFile, ioe); - return false; - } catch (I2PException ie) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Internal error creating new destination", ie); - return false; - } finally { - if (fos != null) try { fos.close(); } catch (IOException ioe) {} - } - } - - FileInputStream fis = null; - try { - fis = new FileInputStream(keyFile); - _session = client.createSession(fis, config); - if (_session == null) { - _log.error("wtf, why did it create a null session?"); - return false; - } - _session.setSessionListener(this); - _session.connect(); - if (_log.shouldLog(Log.INFO)) - _log.info("I2P session created"); - return true; - } catch (IOException ioe) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Unable to read the keystream from " + keyFile, ioe); - return false; - } catch (I2PSessionException ise) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Unable to connect to the router", ise); - return false; - } finally { - if (fis != null) try { fis.close(); } catch (IOException ioe) {} - } - } - - void disconnect() { - if (_session != null) { - try { - _session.destroySession(); - } catch (I2PSessionException ise) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Error destroying the session in shutdown", ise); - } - _session = null; - } - } - - public void disconnected(I2PSession session) { - if (_log.shouldLog(Log.INFO)) - _log.info("Session disconnected"); - } - - public void errorOccurred(I2PSession session, String message, Throwable error) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Session error occurred - " + message, error); - } - - public void messageAvailable(I2PSession session, int msgId, long size) { - if (_log.shouldLog(Log.INFO)) - _log.info("message available [" + msgId + "/"+ size + " bytes]"); - - try { - byte data[] = session.receiveMessage(msgId); - I2PDatagramDissector dissector = new I2PDatagramDissector(); - dissector.loadI2PDatagram(data); - try { - MyI2PMessage msg = new MyI2PMessage(dissector.getSender(), dissector.getPayload()); - _node.handleMessage(msg); - } catch (IllegalArgumentException iae) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Message is a valid datagram but invalid MyI2P message", iae); - } - } catch (I2PSessionException ise) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Error retrieving message payload for message " + msgId, ise); - } catch (I2PInvalidDatagramException iide) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Message received was not a valid repliable datagram", iide); - } catch (DataFormatException dfe) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Message received was a corrupt repliable datagram", dfe); - } - } - - public void reportAbuse(I2PSession session, int severity) { - if (_log.shouldLog(Log.INFO)) - _log.info("abuse occurred"); - } -} diff --git a/apps/myi2p/java/src/net/i2p/myi2p/Service.java b/apps/myi2p/java/src/net/i2p/myi2p/Service.java deleted file mode 100644 index f18f2ebf2..000000000 --- a/apps/myi2p/java/src/net/i2p/myi2p/Service.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.i2p.myi2p; - -import java.util.Properties; -import net.i2p.I2PAppContext; - -/** - * Defines a service that can operate within a MyI2P node, responding to - * messages and performing whatever tasks are necessary. - * - */ -public interface Service { - /** what type of message will this service respond to? */ - public String getType(); - public void setType(String type); - - /** what node is this service hooked into */ - public Node getNode(); - public void setNode(Node node); - - /** what options specific to this node does the service have? */ - public Properties getOptions(); - public void setOptions(Properties opts); - - /** give the service a scope */ - public I2PAppContext getContext(); - public void setContext(I2PAppContext context); - - /** called when a message is received for the service */ - public void receiveMessage(MyI2PMessage msg); - - /** start the service up - the node is ready */ - public void startup(); - /** shut the service down - the node is going offline */ - public void shutdown(); -} diff --git a/apps/myi2p/java/src/net/i2p/myi2p/ServiceImpl.java b/apps/myi2p/java/src/net/i2p/myi2p/ServiceImpl.java deleted file mode 100644 index f5a4ff6c0..000000000 --- a/apps/myi2p/java/src/net/i2p/myi2p/ServiceImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -package net.i2p.myi2p; - -import java.util.Properties; - -import net.i2p.I2PAppContext; -import net.i2p.myi2p.Service; -import net.i2p.myi2p.Node; -import net.i2p.myi2p.MyI2PMessage; - -/** - * Base service implementation - * - */ -public abstract class ServiceImpl implements Service { - private I2PAppContext _context; - private Node _node; - private Properties _options; - private String _serviceType; - - public ServiceImpl() { - _context = null; - _node = null; - _options = null; - _serviceType = null; - } - - // base inspectors / mutators - public Node getNode() { return _node; } - public void setNode(Node node) { _node = node; } - public I2PAppContext getContext() { return _context; } - public void setContext(I2PAppContext context) { _context = context; } - public Properties getOptions() { return _options; } - public void setOptions(Properties opts) { _options = opts; } - public String getType() { return _serviceType; } - public void setType(String type) { _serviceType = type; } -} diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBook.java b/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBook.java deleted file mode 100644 index aa74445d2..000000000 --- a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBook.java +++ /dev/null @@ -1,126 +0,0 @@ -package net.i2p.myi2p.address; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import net.i2p.I2PAppContext; -import net.i2p.data.DataHelper; -import net.i2p.data.DataFormatException; - -/** - * Main lookup component for maintaining references to other I2P destinations. - * - */ -public class AddressBook { - private I2PAppContext _context; - /** Name (String) to AddressBookEntry */ - private Map _entries; - /** - * List of NameReference that has been received but whose preferred - * name conflicts with an existing entry. - */ - private List _conflictingReferences; - - public AddressBook(I2PAppContext context) { - _context = context; - _entries = new HashMap(16); - _conflictingReferences = new ArrayList(0); - } - - /** retrieve a list of entry names (strings) */ - public Set getEntryNames() { - synchronized (_entries) { - return new HashSet(_entries.keySet()); - } - } - public AddressBookEntry getEntry(String name) { - synchronized (_entries) { - return (AddressBookEntry)_entries.get(name); - } - } - public AddressBookEntry addEntry(AddressBookEntry entry) { - synchronized (_entries) { - return (AddressBookEntry)_entries.put(entry.getLocalName(), entry); - } - } - public void removeEntry(String name) { - synchronized (_entries) { - _entries.remove(name); - } - } - - public int getConflictingReferenceCount() { - synchronized (_conflictingReferences) { - return _conflictingReferences.size(); - } - } - public NameReference getConflictingReference(int index) { - synchronized (_conflictingReferences) { - return (NameReference)_conflictingReferences.get(index); - } - } - public void addConflictingReference(NameReference ref) { - synchronized (_conflictingReferences) { - _conflictingReferences.add(ref); - } - } - public void removeConflictingReference(int index) { - synchronized (_conflictingReferences) { - _conflictingReferences.remove(index); - } - } - - public void read(InputStream in) throws IOException { - try { - int numEntries = (int)DataHelper.readLong(in, 2); - if (numEntries < 0) throw new IOException("Corrupt AddressBook - " + numEntries + " entries?"); - for (int i = 0; i < numEntries; i++) { - AddressBookEntry entry = new AddressBookEntry(_context); - entry.read(in); - addEntry(entry); - } - int numConflicting = (int)DataHelper.readLong(in, 2); - if (numConflicting < 0) throw new IOException("Corrupt AddressBook - " + numConflicting + " conflicting?"); - for (int i = 0; i < numConflicting; i++) { - NameReference ref = new NameReference(_context); - ref.read(in); - addConflictingReference(ref); - } - } catch (DataFormatException dfe) { - throw new IOException("Corrupt address book - " + dfe.getMessage()); - } - } - public void write(OutputStream out) throws IOException { - try { - synchronized (_entries) { - DataHelper.writeLong(out, 2, _entries.size()); - for (Iterator iter = _entries.values().iterator(); iter.hasNext(); ) { - AddressBookEntry entry = (AddressBookEntry)iter.next(); - entry.write(out); - } - } - synchronized (_conflictingReferences) { - DataHelper.writeLong(out, 2, _conflictingReferences.size()); - for (int i = 0; i < _conflictingReferences.size(); i++) { - NameReference ref = (NameReference)_conflictingReferences.get(i); - ref.write(out); - } - } - } catch (DataFormatException dfe) { - throw new IOException("Corrupt address book - " + dfe.getMessage()); - } - } - - public String toString() { - return "Entries: " + _entries.size() + " conflicting: " + _conflictingReferences.size(); - } -} diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookEntry.java b/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookEntry.java deleted file mode 100644 index b0f213861..000000000 --- a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookEntry.java +++ /dev/null @@ -1,142 +0,0 @@ -package net.i2p.myi2p.address; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import java.util.Date; -import java.util.Properties; - -import net.i2p.I2PAppContext; -import net.i2p.data.DataHelper; -import net.i2p.data.DataFormatException; - -/** - * Implements a local address book entry, pointing at a known secure - * NameReference as well as an optional Subscription. - * - */ -public class AddressBookEntry { - private I2PAppContext _context; - private String _localName; - private Properties _options; - private NameReference _reference; - private Subscription _subscription; - private long _addedOn; - - public AddressBookEntry(I2PAppContext context) { - _context = context; - _localName = null; - _options = new Properties(); - _reference = null; - _subscription = null; - _addedOn = context.clock().now(); - } - - /** Local (unique) name we use to reference the given destination */ - public String getLocalName() { return _localName; } - public void setLocalName(String name) { _localName = name; } - - public Properties getOptions() { - synchronized (_options) { - return new Properties(_options); - } - } - public void setOptions(Properties props) { - synchronized (_options) { - _options.clear(); - if (props != null) - _options.putAll(props); - } - } - - /** Secure name reference, provided by the destination */ - public NameReference getNameReference() { return _reference; } - public void setNameReference(NameReference ref) { _reference = ref; } - - /** - * If specified, the details of our subscription to the MyI2P address - * book at the referenced destination. - * - */ - public Subscription getSubscription() { return _subscription; } - public void setSubscription(Subscription sub) { _subscription = sub; } - - /** When this entry was added */ - public long getAddedOn() { return _addedOn; } - public void setAddedOn(long when) { _addedOn = when; } - - /** load the data from the stream */ - public void read(InputStream in) throws IOException { - try { - Boolean localNameDefined = DataHelper.readBoolean(in); - if ( (localNameDefined != null) && (localNameDefined.booleanValue()) ) - _localName = DataHelper.readString(in); - else - _localName = null; - - Date when = DataHelper.readDate(in); - if (when == null) - _addedOn = -1; - else - _addedOn = when.getTime(); - - Properties props = DataHelper.readProperties(in); - setOptions(props); - - Boolean refDefined = DataHelper.readBoolean(in); - if ( (refDefined != null) && (refDefined.booleanValue()) ) { - _reference = new NameReference(_context); - _reference.read(in); - } else { - _reference = null; - } - - Boolean subDefined = DataHelper.readBoolean(in); - if ( (subDefined != null) && (subDefined.booleanValue()) ) { - Subscription sub = new Subscription(_context); - sub.read(in); - _subscription = sub; - } else { - _subscription = null; - } - - } catch (DataFormatException dfe) { - throw new IOException("Corrupt subscription: " + dfe.getMessage()); - } - } - - /** persist the data to the stream */ - public void write(OutputStream out) throws IOException { - try { - if ( (_localName != null) && (_localName.trim().length() > 0) ) { - DataHelper.writeBoolean(out, Boolean.TRUE); - DataHelper.writeString(out, _localName); - } else { - DataHelper.writeBoolean(out, Boolean.FALSE); - } - - DataHelper.writeDate(out, new Date(_addedOn)); - - synchronized (_options) { - DataHelper.writeProperties(out, _options); - } - - if (_reference != null) { - DataHelper.writeBoolean(out, Boolean.TRUE); - _reference.write(out); - } else { - DataHelper.writeBoolean(out, Boolean.FALSE); - } - - if (_subscription != null) { - DataHelper.writeBoolean(out, Boolean.TRUE); - _subscription.write(out); - } else { - DataHelper.writeBoolean(out, Boolean.FALSE); - } - } catch (DataFormatException dfe) { - throw new IOException("Corrupt subscription: " + dfe.getMessage()); - } - } -} diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookService.java b/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookService.java deleted file mode 100644 index b42863507..000000000 --- a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookService.java +++ /dev/null @@ -1,90 +0,0 @@ -package net.i2p.myi2p.address; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import net.i2p.data.DataHelper; -import net.i2p.data.DataFormatException; -import net.i2p.util.Log; - -import net.i2p.myi2p.Service; -import net.i2p.myi2p.ServiceImpl; -import net.i2p.myi2p.Node; -import net.i2p.myi2p.MyI2PMessage; - -/** - * Main service handler / coordinator for the MyI2P address book. - * - */ -public class AddressBookService extends ServiceImpl { - private Log _log; - private AddressBook _addressBook; - /** contains a mapping of event time (Long) to description (String) */ - private Map _activityLog; - private String _addressBookFile; - - private static String PROP_ADDRESSBOOK_FILE = "datafile"; - private static String DEFAULT_ADDRESSBOOK_FILE = "addressbook.dat"; - - public static final String SERVICE_TYPE = "AddressBook"; - public String getType() { return SERVICE_TYPE; } - - public void startup() { - _log = getContext().logManager().getLog(AddressBookService.class); - - _addressBookFile = getOptions().getProperty(PROP_ADDRESSBOOK_FILE, DEFAULT_ADDRESSBOOK_FILE); - File file = new File(_addressBookFile); - - if (file.exists()) { - loadData(file); - } else { - _addressBook = new AddressBook(getContext()); - _activityLog = new HashMap(16); - } - } - - public void shutdown() { - File file = new File(_addressBookFile); - storeData(file); - } - - public void receiveMessage(MyI2PMessage msg) { - _log.info("Received a " + msg.getMessageType() + " from " - + msg.getPeer().calculateHash().toBase64() - + new String(msg.getPayload())); - } - - /** load everything from disk */ - private void loadData(File dataFile) { - AddressBookServiceData data = new AddressBookServiceData(getContext()); - data.load(dataFile); - if (data.getErrorMessage() != null) { - _log.warn(data.getErrorMessage(), data.getError()); - _addressBook = new AddressBook(getContext()); - _activityLog = new HashMap(16); - } else { - _addressBook = data.getAddressBook(); - _activityLog = data.getActivityLog(); - } - } - - /** persist everything to disk */ - private void storeData(File dataFile) { - AddressBookServiceData data = new AddressBookServiceData(getContext()); - data.setActivityLog(_activityLog); - data.setAddressBook(_addressBook); - data.store(dataFile); - if (data.getErrorMessage() != null) { - _log.warn(data.getErrorMessage(), data.getError()); - } - } -} diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookServiceData.java b/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookServiceData.java deleted file mode 100644 index 3bfaa8e74..000000000 --- a/apps/myi2p/java/src/net/i2p/myi2p/address/AddressBookServiceData.java +++ /dev/null @@ -1,104 +0,0 @@ -package net.i2p.myi2p.address; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import net.i2p.I2PAppContext; -import net.i2p.data.DataHelper; -import net.i2p.util.Log; - -/** - * Component for loading and storing the service data to disk - * - */ -public class AddressBookServiceData { - private I2PAppContext _context; - private Log _log; - private AddressBook _addressBook; - private Map _activityLog; - private Exception _error; - private String _errorMessage; - - public AddressBookServiceData(I2PAppContext context) { - _context = context; - _log = context.logManager().getLog(AddressBookServiceData.class); - _addressBook = null; - _activityLog = null; - _error = null; - _errorMessage = null; - } - - public AddressBook getAddressBook() { return _addressBook; } - public void setAddressBook(AddressBook book) { _addressBook = book; } - public Map getActivityLog() { return _activityLog; } - public void setActivityLog(Map log) { _activityLog = log; } - - public Exception getError() { return _error; } - public String getErrorMessage() { return _errorMessage; } - - public void load(File from) { - FileInputStream fis = null; - try { - fis = new FileInputStream(from); - AddressBook addressBook = new AddressBook(_context); - addressBook.read(fis); - _addressBook = addressBook; - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Address book: " + addressBook); - Properties props = DataHelper.readProperties(fis); - Map log = new HashMap(props.size()); - for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) { - String key = (String)iter.next(); - String event = props.getProperty(key); - long when = 0; - try { - when = Long.parseLong(key); - while (log.containsKey(new Long(when))) - when++; - log.put(new Long(when), event); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Activity log: on " + new Date(when) + ": " + event); - } catch (NumberFormatException nfe) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Corrupt activity log entry: when=" + key, nfe); - } - } - _activityLog = log; - } catch (Exception e) { - _error = e; - _errorMessage = "Error reading the address book from " + from; - } - } - - public void store(File to) { - FileOutputStream fos = null; - try { - fos = new FileOutputStream(to); - _addressBook.write(fos); - Properties props = new Properties(); - for (Iterator iter = _activityLog.keySet().iterator(); iter.hasNext(); ) { - Long when = (Long)iter.next(); - String msg = (String)_activityLog.get(when); - props.setProperty(when.toString(), msg); - } - DataHelper.writeProperties(fos, props); - } catch (Exception e) { - _error = e; - _errorMessage = "Error writing the address book to " + to; - } finally { - if (fos != null) try { fos.close(); } catch (IOException ioe) {} - } - } -} diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/CreateEntryCLI.java b/apps/myi2p/java/src/net/i2p/myi2p/address/CreateEntryCLI.java deleted file mode 100644 index b90de3c57..000000000 --- a/apps/myi2p/java/src/net/i2p/myi2p/address/CreateEntryCLI.java +++ /dev/null @@ -1,154 +0,0 @@ -package net.i2p.myi2p.address; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; - -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import net.i2p.I2PAppContext; -import net.i2p.data.Destination; -import net.i2p.util.Log; - -/** - * CreateEntryCLI addressBookFile referenceFile localName subscriptionFrequencyHours [ key=value]* - */ -public class CreateEntryCLI { - private I2PAppContext _context; - private String _args[]; - private String _addressBook; - private String _referenceFile; - private String _localName; - private int _subscriptionFrequencyHours; - private Properties _options; - - public CreateEntryCLI(String args[]) { - _context = new I2PAppContext(); - _args = args; - _options = new Properties(); - } - - public void execute() { - if (parseArgs()) - doExecute(); - else - System.err.println("Usage: CreateEntryCLI addressBookFile referenceFile localName subscriptionFrequencyHours[ key=value]*"); - } - - private boolean parseArgs() { - if ( (_args == null) || (_args.length < 3) ) - return false; - _addressBook = _args[0]; - _referenceFile = _args[1]; - _localName = _args[2]; - try { - _subscriptionFrequencyHours = Integer.parseInt(_args[3]); - } catch (NumberFormatException nfe) { - return false; - } - for (int i = 4; i < _args.length; i++) { - int eq = _args[i].indexOf('='); - if ( (eq <= 0) || (eq >= _args[i].length() - 1) ) - continue; - String key = _args[i].substring(0,eq); - String val = _args[i].substring(eq+1); - _options.setProperty(key, val); - } - return true; - } - - private void doExecute() { - AddressBookServiceData data = new AddressBookServiceData(_context); - File f = new File(_addressBook); - if (f.exists()) { - data.load(f); - if (data.getError() != null) { - if (data.getErrorMessage() != null) - System.err.println(data.getErrorMessage()); - data.getError().printStackTrace(); - return; - } - } else { - data.setAddressBook(new AddressBook(_context)); - data.setActivityLog(new HashMap()); - } - NameReference ref = null; - FileInputStream fis = null; - try { - fis = new FileInputStream(_referenceFile); - ref = new NameReference(_context); - ref.read(fis); - } catch (Exception e) { - System.err.println("Name reference under " + _referenceFile + " is corrupt"); - e.printStackTrace(); - return; - } finally { - if (fis != null) try { fis.close(); } catch (IOException ioe) {} - } - - AddressBook book = data.getAddressBook(); - Map activityLog = data.getActivityLog(); - - AddressBookEntry oldEntry = book.getEntry(_localName); - - AddressBookEntry entry = new AddressBookEntry(_context); - entry.setLocalName(_localName); - entry.setNameReference(ref); - - Subscription sub = new Subscription(_context); - sub.setQueryFrequencyMinutes(60*_subscriptionFrequencyHours); - - entry.setSubscription(sub); - entry.setOptions(_options); - - if (oldEntry == null) { - book.addEntry(entry); - System.out.println("New address book entry added for " + entry.getLocalName()); - activityLog.put(new Long(_context.clock().now()), "New address book entry added for " + entry.getLocalName()); - } else { - Destination oldDest = oldEntry.getNameReference().getDestination(); - if (oldDest.equals(ref.getDestination())) { - if (ref.getSequenceNum() < oldEntry.getNameReference().getSequenceNum()) { - System.err.println("Not updating the address book - newer reference for " + entry.getLocalName() + " exists"); - return; - } else { - // same or newer rev - if (null != entry.getSubscription()) { - if (null != oldEntry.getSubscription()) { - entry.getSubscription().setLastQueryAttempt(oldEntry.getSubscription().getLastQueryAttempt()); - entry.getSubscription().setLastQuerySuccess(oldEntry.getSubscription().getLastQuerySuccess()); - } - } - book.addEntry(entry); - System.err.println("Updating the options and subscription for an existing reference to " + entry.getLocalName()); - activityLog.put(new Long(_context.clock().now()), "Updating options and subscription for " + entry.getLocalName()); - } - } else { - book.addConflictingReference(ref); - System.out.println("Old entry exists for " + _localName + " - adding a conflicting reference"); - System.out.println("Existing entry points to " + oldEntry.getNameReference().getDestination().calculateHash().toBase64()); - System.out.println("New entry points to " + entry.getNameReference().getDestination().calculateHash().toBase64()); - - activityLog.put(new Long(_context.clock().now()), "Adding conflicting reference for " + entry.getLocalName()); - } - } - - data.setAddressBook(book); - data.setActivityLog(activityLog); - - data.store(f); - if (data.getError() != null) { - if (data.getErrorMessage() != null) - System.err.println(data.getErrorMessage()); - data.getError().printStackTrace(); - return; - } - } - - public static void main(String args[]) { - CreateEntryCLI cli = new CreateEntryCLI(args); - cli.execute(); - } -} diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/CreateNameReferenceCLI.java b/apps/myi2p/java/src/net/i2p/myi2p/address/CreateNameReferenceCLI.java deleted file mode 100644 index f57ede936..000000000 --- a/apps/myi2p/java/src/net/i2p/myi2p/address/CreateNameReferenceCLI.java +++ /dev/null @@ -1,125 +0,0 @@ -package net.i2p.myi2p.address; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; - -import java.util.Iterator; -import java.util.Properties; - -import net.i2p.I2PAppContext; -import net.i2p.data.Destination; -import net.i2p.data.PrivateKey; -import net.i2p.data.SigningPrivateKey; -import net.i2p.util.Log; - -/** - * CreateNameReferenceCLI outputFile privateDestFile preferredName sequenceNum serviceType[ key=value]* - */ -public class CreateNameReferenceCLI { - private I2PAppContext _context; - private String _args[]; - private String _outputFile; - private String _destFile; - private String _preferredName; - private long _sequenceNum; - private String _serviceType; - private Properties _options; - - public CreateNameReferenceCLI(String[] args) { - _context = new I2PAppContext(); - _args = args; - _options = new Properties(); - } - - public void execute() { - if (parseArgs()) - doExecute(); - else - System.err.println("Usage: CreateNameReferenceCLI outputFile privateDestFile preferredName sequenceNum serviceType[ key=value]*"); - } - - private boolean parseArgs() { - if ( (_args == null) || (_args.length < 4) ) - return false; - _outputFile = _args[0]; - _destFile = _args[1]; - _preferredName = _args[2]; - try { - _sequenceNum = Long.parseLong(_args[3]); - } catch (NumberFormatException nfe) { - return false; - } - _serviceType = _args[4]; - - for (int i = 5; i < _args.length; i++) { - int eq = _args[i].indexOf('='); - if ( (eq <= 0) || (eq >= _args[i].length() - 1) ) - continue; - String key = _args[i].substring(0,eq); - String val = _args[i].substring(eq+1); - _options.setProperty(key, val); - } - return true; - } - - private void doExecute() { - Destination dest = null; - SigningPrivateKey priv = null; - FileInputStream fis = null; - try { - fis = new FileInputStream(_destFile); - dest = new Destination(); - dest.readBytes(fis); - PrivateKey whocares = new PrivateKey(); - whocares.readBytes(fis); - priv = new SigningPrivateKey(); - priv.readBytes(fis); - } catch (Exception e) { - System.err.println("Destination private keys under " + _destFile + " are corrupt"); - e.printStackTrace(); - return; - } finally { - if (fis != null) try { fis.close(); } catch (IOException ioe) {} - } - - NameReference ref = new NameReference(_context); - ref.setDestination(dest); - ref.setPreferredName(_preferredName); - ref.setSequenceNum(_sequenceNum); - ref.setServiceType(_serviceType); - if (_options != null) { - for (Iterator iter = _options.keySet().iterator(); iter.hasNext(); ) { - String key = (String)iter.next(); - String val = _options.getProperty(key); - ref.setOption(key, val); - } - } - - try { - ref.sign(priv); - } catch (IllegalStateException ise) { - System.err.println("Error signing the new reference"); - ise.printStackTrace(); - } - - FileOutputStream fos = null; - try { - fos = new FileOutputStream(_outputFile); - ref.write(fos); - } catch (IOException ioe) { - System.err.println("Error writing out the new reference"); - ioe.printStackTrace(); - } finally { - if (fos != null) try { fos.close(); } catch (IOException ioe) {} - } - - System.out.println("Reference created at " + _outputFile); - } - - public static void main(String args[]) { - CreateNameReferenceCLI cli = new CreateNameReferenceCLI(args); - cli.execute(); - } -} diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/NameReference.java b/apps/myi2p/java/src/net/i2p/myi2p/address/NameReference.java deleted file mode 100644 index c8e597155..000000000 --- a/apps/myi2p/java/src/net/i2p/myi2p/address/NameReference.java +++ /dev/null @@ -1,198 +0,0 @@ -package net.i2p.myi2p.address; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.HashSet; -import java.util.Properties; -import java.util.Set; - -import net.i2p.I2PAppContext; - -import net.i2p.data.DataHelper; -import net.i2p.data.DataFormatException; -import net.i2p.data.Destination; -import net.i2p.data.Signature; -import net.i2p.data.SigningPrivateKey; -import net.i2p.util.Log; - -/** - * Define a verified and immutable reference to a particular I2P destination. - * - */ -public class NameReference { - private I2PAppContext _context; - private Log _log; - private Destination _destination; - private String _preferredName; - private String _serviceType; - private long _sequenceNum; - private Properties _options; - private Signature _signature; - - public static final byte[] VERSION_PREFIX = "MyI2P_NameReference_1.0".getBytes(); - - public NameReference(I2PAppContext context) { - _context = context; - _log = context.logManager().getLog(NameReference.class); - _destination = null; - _preferredName = null; - _serviceType = null; - _sequenceNum = -1; - _options = new Properties(); - _signature = null; - } - - /** retrieve the destination this reference points at */ - public Destination getDestination() { return _destination; } - public void setDestination(Destination dest) { _destination = dest; } - - /** retrieve the name this destination would like to be called */ - public String getPreferredName() { return _preferredName; } - public void setPreferredName(String name) { _preferredName = name; } - - /** retrieve the type of service at this destination (eepsite, ircd, etc) */ - public String getServiceType() { return _serviceType; } - public void setServiceType(String type) { _serviceType = type; } - - /** - * data point to allow the reference to be updated. The reference with the - * larger sequence number should clobber an older reference. - * - */ - public long getSequenceNum() { return _sequenceNum; } - public void setSequenceNum(long num) { _sequenceNum = num; } - - /** Get a list of option names (strings) */ - public Set getOptionNames() { return new HashSet(_options.keySet()); } - - /** Access any options published in the reference */ - public String getOption(String name) { return (String)_options.getProperty(name); } - - /** - * Specify a particular value for an option. If the value is null, the - * entry is removed. The name cannot have an '=' or newline, and the - * value cannot have a newline. - * - * @throws IllegalArgumentException if the name or value is illegal - */ - public void setOption(String name, String value) { - if (name == null) throw new IllegalArgumentException("Missing name"); - if (name.indexOf('=') != -1) - throw new IllegalArgumentException("Name cannot have an = sign"); - if (name.indexOf('\n') != -1) - throw new IllegalArgumentException("Name cannot have a newline"); - - if (value != null) { - if (value.indexOf('\n') != -1) - throw new IllegalArgumentException("Values do not allow newlines"); - _options.setProperty(name, value); - } else { - _options.remove(name); - } - } - - /** Access the DSA signature authenticating this reference */ - public Signature getSignature() { return _signature; } - public void setSignature(Signature sig) { _signature = sig; } - - /** Verify the DSA signature, returning true if it is valid, false otherwise */ - public boolean validate() { - try { - byte raw[] = toSignableByteArray(); - return _context.dsa().verifySignature(_signature, raw, _destination.getSigningPublicKey()); - } catch (IllegalStateException ise) { - return false; - } - } - - /** - * Sign the data - * - * @throws IllegalStateException if the data is invalid - */ - public void sign(SigningPrivateKey key) throws IllegalStateException { - byte signable[] = toSignableByteArray(); - _signature = _context.dsa().sign(signable, key); - } - - /** - * Retrieve the full serialized and signed version of this name reference - * - * @throws IllegalStateException if the signature or other data is invalid - */ - public void write(OutputStream out) throws IllegalStateException, IOException { - if (_signature == null) throw new IllegalStateException("No signature"); - byte signable[] = toSignableByteArray(); - out.write(signable); - try { - _signature.writeBytes(out); - } catch (DataFormatException dfe) { - throw new IllegalStateException("Signature was corrupt - " + dfe.getMessage()); - } - } - - /** - * Retrieve the signable (but not including the signature) name reference - * - * @throws IllegalStateException if the data is invalid - */ - private byte[] toSignableByteArray() throws IllegalStateException { - if (_sequenceNum < 0) throw new IllegalStateException("Sequence number is invalid"); - if (_preferredName == null) throw new IllegalStateException("Preferred name is invalid"); - if (_serviceType == null) throw new IllegalStateException("Service type is invalid"); - if (_options == null) throw new IllegalStateException("Options not constructed"); - if (_destination == null) throw new IllegalStateException("Destination not specified"); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(512); - try { - baos.write(VERSION_PREFIX); - _destination.writeBytes(baos); - DataHelper.writeLong(baos, 4, _sequenceNum); - DataHelper.writeString(baos, _preferredName); - DataHelper.writeString(baos, _serviceType); - DataHelper.writeProperties(baos, _options); // sorts alphabetically - return baos.toByteArray(); - } catch (DataFormatException dfe) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Corrupted trying to write entry", dfe); - return null; - } catch (IOException ioe) { - if (_log.shouldLog(Log.ERROR)) - _log.error("IOError writing to memory?", ioe); - return null; - } - } - - /** - * Read a full signed reference from the given stream - * - * @throws DataFormatException if the reference is corrupt - * @throws IOException if there is an error reading the stream - */ - public void read(InputStream in) throws DataFormatException, IOException { - byte versionBuf[] = new byte[VERSION_PREFIX.length]; - int len = DataHelper.read(in, versionBuf); - if (len != versionBuf.length) - throw new IllegalArgumentException("Version length too short ("+ len + ")"); - if (!DataHelper.eq(versionBuf, VERSION_PREFIX)) - throw new IllegalArgumentException("Version mismatch (" + new String(versionBuf) + ")"); - Destination dest = new Destination(); - dest.readBytes(in); - long seq = DataHelper.readLong(in, 4); - String name = DataHelper.readString(in); - String type = DataHelper.readString(in); - Properties opts = DataHelper.readProperties(in); - Signature sig = new Signature(); - sig.readBytes(in); - - // ok, nothing b0rked - _destination = dest; - _sequenceNum = seq; - _preferredName = name; - _serviceType = type; - _options = opts; - _signature = sig; - } -} diff --git a/apps/myi2p/java/src/net/i2p/myi2p/address/Subscription.java b/apps/myi2p/java/src/net/i2p/myi2p/address/Subscription.java deleted file mode 100644 index 0680fc6a2..000000000 --- a/apps/myi2p/java/src/net/i2p/myi2p/address/Subscription.java +++ /dev/null @@ -1,66 +0,0 @@ -package net.i2p.myi2p.address; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import java.util.Date; - -import net.i2p.I2PAppContext; -import net.i2p.data.DataHelper; -import net.i2p.data.DataFormatException; - -/** - * Contains the preferences for subscribing to a particular peer's address - * book. - */ -public class Subscription { - private I2PAppContext _context; - private int _queryFrequencyMinutes; - private long _lastQueryAttempt; - private long _lastQuerySuccess; - - /** no subscription more often than 4 times a day */ - public static final int MIN_FREQUENCY = 6*60*60*1000; - - public Subscription(I2PAppContext context) { - _context = context; - } - - /** how often do we want to query the peer (in minutes) */ - public int getQueryFrequencyMinutes() { return _queryFrequencyMinutes; } - public void setQueryFrequencyMinutes(int freq) { _queryFrequencyMinutes = freq; } - - /** when did we last successfully query the peer */ - public long getLastQuerySuccess() { return _lastQuerySuccess; } - public void setLastQuerySuccess(long when) { _lastQuerySuccess = when; } - - /** when did we last attempt to query the peer */ - public long getLastQueryAttempt() { return _lastQueryAttempt; } - public void setLastQueryAttempt(long when) { _lastQueryAttempt = when; } - - /** load the data from the stream */ - public void read(InputStream in) throws IOException { - try { - int freq = (int)DataHelper.readLong(in, 2); - Date attempt = DataHelper.readDate(in); - Date success = DataHelper.readDate(in); - _queryFrequencyMinutes = (freq < MIN_FREQUENCY ? MIN_FREQUENCY : freq); - _lastQueryAttempt = (attempt != null ? attempt.getTime() : -1); - _lastQuerySuccess = (success != null ? success.getTime() : -1); - } catch (DataFormatException dfe) { - throw new IOException("Corrupt subscription: " + dfe.getMessage()); - } - } - - /** persist the data to the stream */ - public void write(OutputStream out) throws IOException { - try { - DataHelper.writeLong(out, 2, _queryFrequencyMinutes); - DataHelper.writeDate(out, new Date(_lastQueryAttempt)); - DataHelper.writeDate(out, new Date(_lastQuerySuccess)); - } catch (DataFormatException dfe) { - throw new IOException("Corrupt subscription: " + dfe.getMessage()); - } - } -} diff --git a/apps/myi2p/myi2p.config b/apps/myi2p/myi2p.config deleted file mode 100644 index 2d66d576c..000000000 --- a/apps/myi2p/myi2p.config +++ /dev/null @@ -1,3 +0,0 @@ -keyFile=myi2p.keys -service.0.classname=net.i2p.myi2p.address.AddressBookService -service.0.type=AddressBook \ No newline at end of file diff --git a/apps/netmonitor/harvester.config b/apps/netmonitor/harvester.config deleted file mode 100644 index 91f333224..000000000 --- a/apps/netmonitor/harvester.config +++ /dev/null @@ -1,130 +0,0 @@ -# dropped jobs -statGroup.0.name=droppedJobs -statGroup.0.detail.0.name=num dropped jobs (minute) -statGroup.0.detail.0.option=stat_jobQueue.droppedJobs.60m -statGroup.0.detail.0.field=3 -statGroup.0.detail.1.name=num dropped jobs (hour) -statGroup.0.detail.1.option=stat_jobQueue.droppedJobs.60h -statGroup.0.detail.1.field=3 -# -statGroup.1.name=encryptTime -statGroup.1.detail.0.name=encryption time avg ms (minute) -statGroup.1.detail.0.option=stat_crypto.elGamal.encrypt.60s -statGroup.1.detail.0.field=0 -statGroup.1.detail.1.name=num encryptions (minute) -statGroup.1.detail.1.option=stat_crypto.elGamal.encrypt.60s -statGroup.1.detail.1.field=7 -statGroup.1.detail.2.name=encryption time avg ms (hour) -statGroup.1.detail.2.option=stat_crypto.elGamal.encrypt.60s -statGroup.1.detail.2.field=0 -statGroup.1.detail.3.name=num encryptions (hour) -statGroup.1.detail.3.option=stat_crypto.elGamal.encrypt.60s -statGroup.1.detail.3.field=7 -# -statGroup.2.name=processingTime -statGroup.2.detail.0.name=process time avg ms (minute) -statGroup.2.detail.0.option=stat_transport.sendProcessingTime.60s -statGroup.2.detail.0.field=0 -statGroup.2.detail.1.name=process events (minute) -statGroup.2.detail.1.option=stat_transport.sendProcessingTime.60s -statGroup.2.detail.1.field=7 -statGroup.2.detail.2.name=process time avg ms (hour) -statGroup.2.detail.2.option=stat_transport.sendProcessingTime.60m -statGroup.2.detail.2.field=0 -statGroup.2.detail.3.name=process events(hour) -statGroup.2.detail.3.option=stat_transport.sendProcessingTime.60m -statGroup.2.detail.3.field=7 -# -statGroup.3.name=jobInfo -statGroup.3.detail.0.name=job run avg ms (minute) -statGroup.3.detail.0.option=stat_jobQueue.jobRun.60s -statGroup.3.detail.0.field=0 -statGroup.3.detail.1.name=job lag avg ms (minute) -statGroup.3.detail.1.option=stat_jobQueue.jobLag.60s -statGroup.3.detail.1.field=0 -statGroup.3.detail.2.name=job count (minute) -statGroup.3.detail.2.option=stat_jobQueue.jobRun.60s -statGroup.3.detail.2.field=7 -statGroup.3.detail.3.name=job run avg ms (hour) -statGroup.3.detail.3.option=stat_jobQueue.jobRun.60m -statGroup.3.detail.3.field=0 -statGroup.3.detail.4.name=job lag avg ms (hour) -statGroup.3.detail.4.option=stat_jobQueue.jobLag.60m -statGroup.3.detail.4.field=0 -statGroup.3.detail.5.name=job count (hour) -statGroup.3.detail.5.option=stat_jobQueue.jobRun.60m -statGroup.3.detail.5.field=7 -# -statGroup.4.name=tunnels -statGroup.4.detail.0.name=participating tunnels count (5 minutes) -statGroup.4.detail.0.option=stat_tunnel.participatingTunnels.5m -statGroup.4.detail.0.field=0 -statGroup.4.detail.1.name=participating tunnels joined (5 minutes) -statGroup.4.detail.1.option=stat_tunnel.participatingTunnels.5m -statGroup.4.detail.1.field=3 -statGroup.4.detail.2.name=participating tunnels count (hour) -statGroup.4.detail.2.option=stat_tunnel.participatingTunnels.60m -statGroup.4.detail.2.field=0 -statGroup.4.detail.3.name=participating tunnels joined (hour) -statGroup.4.detail.3.option=stat_tunnel.participatingTunnels.60m -statGroup.4.detail.3.field=3 -# -statGroup.5.name=transfer -statGroup.5.detail.0.name=messages sent (5 minutes) -statGroup.5.detail.0.option=stat_transport.sendMessageSize.5m -statGroup.5.detail.0.field=7 -statGroup.5.detail.1.name=send message size avg (5 minutes) -statGroup.5.detail.1.option=stat_transport.sendMessageSize.5m -statGroup.5.detail.1.field=0 -statGroup.5.detail.2.name=messages sent (hour) -statGroup.5.detail.2.option=stat_transport.sendMessageSize.60m -statGroup.5.detail.2.field=7 -statGroup.5.detail.3.name=send message size avg (hour) -statGroup.5.detail.3.option=stat_transport.sendMessageSize.60m -statGroup.5.detail.3.field=0 -statGroup.5.detail.4.name=messages received (5 minutes) -statGroup.5.detail.4.option=stat_transport.receiveMessageSize.5m -statGroup.5.detail.4.field=7 -statGroup.5.detail.5.name=receive message size avg (5 minutes) -statGroup.5.detail.5.option=stat_transport.receiveMessageSize.5m -statGroup.5.detail.5.field=0 -statGroup.5.detail.6.name=messages received (hour) -statGroup.5.detail.6.option=stat_transport.receiveMessageSize.60m -statGroup.5.detail.6.field=7 -statGroup.5.detail.7.name=receive message size avg (hour) -statGroup.5.detail.7.option=stat_transport.receiveMessageSize.60m -statGroup.5.detail.7.field=0 -# -statGroup.6.name=networkDbHandling -statGroup.6.detail.0.name=lookups received (5 minutes) -statGroup.6.detail.0.option=stat_netDb.lookupsReceived.5m -statGroup.6.detail.0.field=3 -statGroup.6.detail.1.name=lookups handled (5 minutes) -statGroup.6.detail.1.option=stat_netDb.lookupsHandled.5m -statGroup.6.detail.1.field=3 -statGroup.6.detail.2.name=lookups matched (5 minutes) -statGroup.6.detail.2.option=stat_netDb.lookupsReceived.5m -statGroup.6.detail.2.field=3 -statGroup.6.detail.3.name=lookups received (hour) -statGroup.6.detail.3.option=stat_netDb.lookupsReceived.60m -statGroup.6.detail.3.field=3 -statGroup.6.detail.4.name=lookups handled (hour) -statGroup.6.detail.4.option=stat_netDb.lookupsHandled.60m -statGroup.6.detail.4.field=3 -statGroup.6.detail.5.name=lookups matched (hour) -statGroup.6.detail.5.option=stat_netDb.lookupsReceived.60m -statGroup.6.detail.5.field=3 -# -statGroup.7.name=networkDbActivity -statGroup.7.detail.0.name=lookups sent (hour) -statGroup.7.detail.0.option=stat_netDb.successPeers.60m -statGroup.7.detail.0.field=3 -statGroup.7.detail.1.name=lookup peers (hour) -statGroup.7.detail.1.option=stat_netDb.successPeers.60m -statGroup.7.detail.1.field=0 -statGroup.7.detail.2.name=db store sent (5 minutes) -statGroup.7.detail.2.option=stat_netDb.storeSent.5m -statGroup.7.detail.2.field=3 -statGroup.7.detail.3.name=db store sent (hour) -statGroup.7.detail.3.option=stat_netDb.storeSent.60m -statGroup.7.detail.3.field=3 \ No newline at end of file diff --git a/apps/netmonitor/java/build.xml b/apps/netmonitor/java/build.xml deleted file mode 100644 index a46304556..000000000 --- a/apps/netmonitor/java/build.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/DataHarvester.java b/apps/netmonitor/java/src/net/i2p/netmonitor/DataHarvester.java deleted file mode 100644 index 6d14a8174..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/DataHarvester.java +++ /dev/null @@ -1,245 +0,0 @@ -package net.i2p.netmonitor; - -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Properties; -import java.util.StringTokenizer; - -import net.i2p.data.RouterInfo; -import net.i2p.util.Clock; -import net.i2p.util.Log; - -/** - * Pull out important data from the published routerInfo and stash it away - * in the netMonitor - * - */ -class DataHarvester { - private static final Log _log = new Log(DataHarvester.class); - private static final DataHarvester _instance = new DataHarvester(); - public static final DataHarvester getInstance() { return _instance; } - /** - * Contains the list of StatGroup objects loaded from the harvest.config file - * {@see StatGroupLoader} where each statGroup defines a set of stats to pull - * from each router's options. - * - */ - private List _statGroups; - - /** - * Where are we reading the stat groups from? For now, "harvester.config". - */ - private static final String STAT_GROUP_CONFIG_FILENAME = "harvester.config"; - - protected DataHarvester() { - _statGroups = StatGroupLoader.loadStatGroups(STAT_GROUP_CONFIG_FILENAME); - } - - /** - * Harvest all of the data from the peers and store it in the monitor. - * - * @param peers list of RouterInfo structures to harvest from - */ - public void harvestData(NetMonitor monitor, List peers) { - for (int i = 0; i < peers.size(); i++) { - harvestData(monitor, (RouterInfo)peers.get(i), peers); - } - } - - /** - * Pull out all the data we can for the specified peer - * - * @param peer who are we focusing on in this pass - * @param peers everyone on the network, to co - */ - private void harvestData(NetMonitor monitor, RouterInfo peer, List peers) { - _log.info("Harvest the data from " + peer.getIdentity().getHash().toBase64()); - harvestRank(monitor, peer, peers); - harvestRankAs(monitor, peer); - harvestGroups(monitor, peer); - } - - /** - * How does the peer rank other routers? Stored in the peer summary as - * "rankAs", containing 4 longs (numFast, numReliable, numNotFailing, numFailing) - * - * @param peer who is doing the ranking - */ - private void harvestRankAs(NetMonitor monitor, RouterInfo peer) { - int numFast = 0; - int numHighCapacity = 0; - int numNotFailing = 0; - int numFailing = 0; - - Properties props = peer.getOptions(); - for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) { - String key = (String)iter.next(); - if (key.startsWith("profile.")) { - String val = (String)props.get(key); - if (val.indexOf("fast") != -1) - numFast++; - else if (val.indexOf("highCapacity") != -1) - numHighCapacity++; - else if (val.indexOf("notFailing") != -1) - numNotFailing++; - else if (val.indexOf("failing") != -1) - numFailing++; - } - } - - long rankAs[] = new long[4]; - rankAs[0] = numFast; - rankAs[1] = numHighCapacity; - rankAs[2] = numNotFailing; - rankAs[3] = numFailing; - String description = "how we rank peers"; - String valDescr[] = new String[4]; - valDescr[0] = "# peers we rank as fast"; - valDescr[1] = "# peers we rank as high capacity"; - valDescr[2] = "# peers we rank as not failing"; - valDescr[3] = "# peers we rank as failing"; - monitor.addData(peer.getIdentity().getHash().toBase64(), "rankAs", description, valDescr, peer.getPublished(), rankAs); - } - - /** - * How do other peers rank the current peer? Stored in the peer summary as - * "rank", containing 4 longs (numFast, numReliable, numNotFailing, numFailing) - * - * @param peer who do we want to check the network's perception of - * @param peers peers whose rankings we will use - */ - private void harvestRank(NetMonitor monitor, RouterInfo peer, List peers) { - int numFast = 0; - int numHighCapacity = 0; - int numNotFailing = 0; - int numFailing = 0; - - // now count 'em - for (int i = 0; i < peers.size(); i++) { - RouterInfo cur = (RouterInfo)peers.get(i); - if (peer == cur) continue; - String prop = "profile." + peer.getIdentity().getHash().toBase64().replace('=', '_'); - String val = cur.getOptions().getProperty(prop); - if ( (val == null) || (val.length() <= 0) ) continue; - if (val.indexOf("fast") != -1) - numFast++; - else if (val.indexOf("highCapacity") != -1) - numHighCapacity++; - else if (val.indexOf("notFailing") != -1) - numNotFailing++; - else if (val.indexOf("failing") != -1) - numFailing++; - } - - long rank[] = new long[4]; - rank[0] = numFast; - rank[1] = numHighCapacity; - rank[2] = numNotFailing; - rank[3] = numFailing; - String description = "how peers rank us"; - String valDescr[] = new String[4]; - valDescr[0] = "# peers ranking us as fast"; - valDescr[1] = "# peers ranking us as high capacity"; - valDescr[2] = "# peers ranking us as not failing"; - valDescr[3] = "# peers ranking us as failing"; - // we use the current date, not the published date, since this sample doesnt come from them - monitor.addData(peer.getIdentity().getHash().toBase64(), "rank", description, valDescr, Clock.getInstance().now(), rank); - } - - /** - * Harvest all data points from the peer - * - */ - private void harvestGroups(NetMonitor monitor, RouterInfo peer) { - _log.debug("Harvesting group data for " + peer.getIdentity().getHash().toBase64()); - for (int i = 0; i < _statGroups.size(); i++) { - StatGroup group = (StatGroup)_statGroups.get(i); - harvestGroup(monitor, peer, group); - } - } - - /** - * Harvest the data points for the given group from the peer and toss them - * into the monitor - * - */ - private void harvestGroup(NetMonitor monitor, RouterInfo peer, StatGroup group) { - _log.debug("Harvesting group data for " + peer.getIdentity().getHash().toBase64() + " / " + group.getDescription()); - double values[] = harvestGroupValues(peer, group); - if (values == null) return; - - String valDescr[] = new String[group.getStatCount()]; - for (int i = 0; i < group.getStatCount(); i++) - valDescr[i] = group.getStat(i).getStatDescription(); - monitor.addData(peer.getIdentity().getHash().toBase64(), group.getDescription(), group.getDescription(), valDescr, peer.getPublished(), values); - } - - /** - * Pull up a list of all values associated with the group (in the order that the - * group specifies). - * - * @return values or null on error - */ - private double[] harvestGroupValues(RouterInfo peer, StatGroup group) { - List values = new ArrayList(8); - for (int i = 0; i < group.getStatCount(); i++) { - StatGroup.StatDescription stat = group.getStat(i); - double val = getDouble(peer, stat.getOptionName(), stat.getOptionField()); - if (val == -1) - return null; - else - values.add(new Double(val)); - } - double rv[] = new double[values.size()]; - for (int i = 0; i < values.size(); i++) - rv[i] = ((Double)values.get(i)).doubleValue(); - return rv; - } - - /** - * Pull a value from the peer's option as a double, assuming the standard semicolon - * delimited formatting - * - * @param peer peer to query - * @param key peer option to check - * @param index 0-based index into the semicolon delimited values to pull out - * @return value, or -1 if there was an error - */ - private static final double getDouble(RouterInfo peer, String key, int index) { - String val = peer.getOptions().getProperty(key); - if (val == null) return -1; - StringTokenizer tok = new StringTokenizer(val, ";"); - for (int i = 0; i < index; i++) { - if (!tok.hasMoreTokens()) return -1; - tok.nextToken(); // ignore - } - if (!tok.hasMoreTokens()) return -1; - String cur = tok.nextToken(); - try { - return getDoubleValue(cur); - } catch (ParseException pe) { - _log.warn("Unable to parse out the double from field " + index + " out of " + val + " for " + key, pe); - return -1; - } - } - - /** this mimics the format used in the router's StatisticsManager */ - private static final DecimalFormat _numFmt = new DecimalFormat("###,###,###,###,##0.00", new DecimalFormatSymbols(Locale.UK)); - - /** - * Converts a number (double) to text - * @param val the number to convert - * @return the textual representation - */ - private static final double getDoubleValue(String val) throws ParseException { - synchronized (_numFmt) { - Number n = _numFmt.parse(val); - return n.doubleValue(); - } - } -} \ No newline at end of file diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/NetMonitor.java b/apps/netmonitor/java/src/net/i2p/netmonitor/NetMonitor.java deleted file mode 100644 index 5fdf1aab7..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/NetMonitor.java +++ /dev/null @@ -1,251 +0,0 @@ -package net.i2p.netmonitor; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FilenameFilter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import net.i2p.util.I2PThread; -import net.i2p.util.Log; - -/** - * Main driver for the app that harvests data about the performance of the network, - * building summaries for each peer that change over time.

- * - * Usage: NetMonitor [configFilename] [--routers filename[,filename]*] [--netDbURL url]

- * - * - * - */ -public class NetMonitor { - private static final Log _log = new Log(NetMonitor.class); - public static final String CONFIG_LOCATION_DEFAULT = "netmonitor.config"; - public static final String HARVEST_DELAY_PROP = "harvestDelaySeconds"; - public static final int HARVEST_DELAY_DEFAULT = 5*60; - public static final String EXPORT_DELAY_PROP = "exportDelaySeconds"; - public static final int EXPORT_DELAY_DEFAULT = 120; - public static final String SUMMARY_DURATION_PROP = "summaryDurationHours"; - public static final int SUMMARY_DURATION_DEFAULT = 72; - public static final String NETDB_DIR_PROP = "netDbDir"; - public static final String NETDB_DIR_DEFAULT = "netDb"; - public static final String EXPORT_DIR_PROP = "exportDir"; - public static final String EXPORT_DIR_DEFAULT = "monitorData"; - private String _configLocation; - private int _harvestDelay; - private int _exportDelay; - private String _exportDir; - private String _netDbDir; - private String _netDbURL; - private String _explicitRouters; - private int _summaryDurationHours; - private boolean _isRunning; - private Map _peerSummaries; - - public NetMonitor() { - this(CONFIG_LOCATION_DEFAULT, null, null); - } - public NetMonitor(String configLocation) { - this(configLocation, null, null); - } - public NetMonitor(String configLocation, String explicitFilenames, String url) { - _configLocation = configLocation; - _explicitRouters = explicitFilenames; - _netDbURL = url; - _peerSummaries = new HashMap(32); - loadConfig(); - } - - /** read and call parse */ - private void loadConfig() { - Properties props = new Properties(); - FileInputStream fis = null; - try { - fis = new FileInputStream(_configLocation); - props.load(fis); - } catch (IOException ioe) { - _log.warn("Error loading the net monitor config", ioe); - } finally { - if (fis != null) try { fis.close(); } catch (IOException ioe) {} - } - parseConfig(props); - } - - /** interpret the config elements and shove 'em in the vars */ - private void parseConfig(Properties props) { - String val = props.getProperty(HARVEST_DELAY_PROP, ""+HARVEST_DELAY_DEFAULT); - try { - _harvestDelay = Integer.parseInt(val); - } catch (NumberFormatException nfe) { - _log.warn("Error parsing the harvest delay [" + val + "]", nfe); - _harvestDelay = HARVEST_DELAY_DEFAULT; - } - - val = props.getProperty(EXPORT_DELAY_PROP, ""+EXPORT_DELAY_DEFAULT); - try { - _exportDelay = Integer.parseInt(val); - } catch (NumberFormatException nfe) { - _log.warn("Error parsing the export delay [" + val + "]", nfe); - _exportDelay = EXPORT_DELAY_DEFAULT; - } - - val = props.getProperty(SUMMARY_DURATION_PROP, ""+SUMMARY_DURATION_DEFAULT); - try { - _summaryDurationHours = Integer.parseInt(val); - } catch (NumberFormatException nfe) { - _log.warn("Error parsing the summary duration [" + val + "]", nfe); - _summaryDurationHours = SUMMARY_DURATION_DEFAULT; - } - - _netDbDir = props.getProperty(NETDB_DIR_PROP, NETDB_DIR_DEFAULT); - _exportDir = props.getProperty(EXPORT_DIR_PROP, EXPORT_DIR_DEFAULT); - } - - public void startMonitor() { - _isRunning = true; - I2PThread t = new I2PThread(new NetMonitorRunner(this)); - t.setName("DataHarvester"); - t.setPriority(I2PThread.MIN_PRIORITY); - t.setDaemon(false); - t.start(); - } - - public void stopMonitor() { _isRunning = false; } - public boolean isRunning() { return _isRunning; } - /** how many seconds should we wait between harvestings? */ - public int getHarvestDelay() { return _harvestDelay; } - /** how many seconds should we wait between exporting the data? */ - public int getExportDelay() { return _exportDelay; } - /** where should we export the data? */ - public String getExportDir() { return _exportDir; } - public void setExportDir(String dir) { _exportDir = dir; } - public int getSummaryDurationHours() { return _summaryDurationHours; } - /** where should we read the data from? */ - public String getNetDbDir() { return _netDbDir; } - /** if specified, contains a set of filenames we want to harvest routerInfo data from */ - public String getExplicitRouters() { return _explicitRouters; } - /** if specified, contains a URL to fetch references from */ - public String getNetDbURL() { return _netDbURL; } - - /** - * what peers are we keeping track of? - * - * @return list of peer names (H(routerIdentity).toBase64()) - */ - public List getPeers() { - synchronized (_peerSummaries) { - return new ArrayList(_peerSummaries.keySet()); - } - } - - /** what data do we have for the peer? */ - public PeerSummary getSummary(String peer) { - synchronized (_peerSummaries) { - return (PeerSummary)_peerSummaries.get(peer); - } - } - - /** keep track of the given stat on the given peer */ - public void addData(String peer, String stat, String descr, String valDescr[], long sampleDate, double val[]) { - synchronized (_peerSummaries) { - if (!_peerSummaries.containsKey(peer)) - _peerSummaries.put(peer, new PeerSummary(peer)); - PeerSummary summary = (PeerSummary)_peerSummaries.get(peer); - summary.addData(stat, descr, valDescr, sampleDate, val); - } - } - - /** keep track of the given stat on the given peer */ - public void addData(String peer, String stat, String descr, String valDescr[], long sampleDate, long val[]) { - synchronized (_peerSummaries) { - if (!_peerSummaries.containsKey(peer)) - _peerSummaries.put(peer, new PeerSummary(peer)); - PeerSummary summary = (PeerSummary)_peerSummaries.get(peer); - summary.addData(stat, descr, valDescr, sampleDate, val); - } - } - - /** keep track of the loaded summary, overwriting any existing summary for the specified peer */ - public void addSummary(PeerSummary summary) { - synchronized (_peerSummaries) { - Object rv = _peerSummaries.put(summary.getPeer(), summary); - if (rv != summary) _log.error("Updating the peer summary changed objects! old = " + rv + " new = " + summary); - } - } - - public void importData() { - _log.debug("Running import"); - File dataDir = new File(getExportDir()); - if (!dataDir.exists()) return; - File dataFiles[] = dataDir.listFiles(new FilenameFilter() { - public boolean accept(File f, String name) { - return name.endsWith(".txt"); - } - }); - if (dataFiles == null) return; - for (int i = 0; i < dataFiles.length; i++) { - FileInputStream fis = null; - boolean delete = false; - try { - fis = new FileInputStream(dataFiles[i]); - PeerSummaryReader.getInstance().read(this, fis); - } catch (IOException ioe) { - _log.error("Error reading the data file " + dataFiles[i].getAbsolutePath(), ioe); - delete = true; - } finally { - if (fis != null) try { fis.close(); } catch (IOException ioe) {} - if (delete) dataFiles[i].delete(); - } - } - _log.debug(dataFiles.length + " summaries imported"); - } - - /** drop all the old summary data */ - public void coalesceData() { - synchronized (_peerSummaries) { - for (Iterator iter = _peerSummaries.values().iterator(); iter.hasNext(); ) { - PeerSummary summary = (PeerSummary)iter.next(); - summary.coalesceData(_summaryDurationHours * 60*60*1000); - } - } - } - - /** - * main driver for the netMonitor. the usage is: - * NetMonitor [configFilename] [--routers filename[,filename]*] [--netDbURL url] - */ - public static final void main(String args[]) { - String cfgLocation = CONFIG_LOCATION_DEFAULT; - String explicitFilenames = null; - String explicitURL = null; - switch (args.length) { - case 0: - break; - case 1: - cfgLocation = args[0]; - break; - case 2: - if ("--routers".equalsIgnoreCase(args[0])) - explicitFilenames = args[1]; - else - explicitURL = args[1]; - break; - case 3: - cfgLocation = args[0]; - if ("--routers".equalsIgnoreCase(args[1])) - explicitFilenames = args[2]; - else - explicitURL = args[2]; - break; - default: - System.err.println("Usage: NetMonitor [configFilename] [--routers filename[,filename]*] [--netDbURL url]"); - return; - } - new NetMonitor(cfgLocation, explicitFilenames, explicitURL).startMonitor(); - } -} diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/NetMonitorRunner.java b/apps/netmonitor/java/src/net/i2p/netmonitor/NetMonitorRunner.java deleted file mode 100644 index 0df06f76e..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/NetMonitorRunner.java +++ /dev/null @@ -1,242 +0,0 @@ -package net.i2p.netmonitor; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.StringTokenizer; - -import net.i2p.data.DataFormatException; -import net.i2p.data.RouterInfo; -import net.i2p.util.Clock; -import net.i2p.util.Log; - -/** - * Active process that drives the monitoring by periodically rading the - * netDb dir, pumping the router data throug the data harvester, updating - * the state, and coordinating the export. - * - */ -class NetMonitorRunner implements Runnable { - private static final Log _log = new Log(NetMonitorRunner.class); - private NetMonitor _monitor; - /** - * @param monitor who do we give our data to? - */ - public NetMonitorRunner(NetMonitor monitor) { - _monitor = monitor; - } - - public void run() { - runImport(); - long now = Clock.getInstance().now(); - long nextHarvest = now; - long nextExport = now + _monitor.getExportDelay() * 1000; - while (_monitor.isRunning()) { - now = Clock.getInstance().now(); - _monitor.coalesceData(); - if (now >= nextHarvest) { - runHarvest(); - nextHarvest = now + _monitor.getHarvestDelay() * 1000; - } - if (now >= nextExport) { - runExport(); - nextExport = now + _monitor.getExportDelay() * 1000; - } - pauseHarvesting(); - } - } - - private void runHarvest() { - try { - List routers = getRouters(); - DataHarvester.getInstance().harvestData(_monitor, routers); - } catch (Throwable t) { - _log.error("Unhandled exception harvesting the data", t); - } - } - - /** - * Fetch all of the available RouterInfo structures - * - */ - private List getRouters() { - if (_monitor.getNetDbURL() != null) - return fetchRouters(_monitor.getNetDbURL()); - - File routers[] = listRouters(); - List rv = new ArrayList(64); - if (routers != null) { - for (int i = 0; i < routers.length; i++) { - FileInputStream fis = null; - try { - fis = new FileInputStream(routers[i]); - RouterInfo ri = new RouterInfo(); - ri.readBytes(fis); - rv.add(ri); - } catch (DataFormatException dfe) { - _log.warn("Unable to parse the routerInfo from " + routers[i].getAbsolutePath(), dfe); - } catch (IOException ioe) { - _log.warn("Unable to read the routerInfo from " + routers[i].getAbsolutePath(), ioe); - } finally { - if (fis != null) try { fis.close(); } catch (IOException ioe) {} - } - } - } - return rv; - } - - - private List fetchRouters(String seedURL) { - List rv = new ArrayList(); - try { - URL dir = new URL(seedURL); - String content = new String(readURL(dir)); - Set urls = new HashSet(); - int cur = 0; - while (true) { - int start = content.indexOf("href=\"routerInfo-", cur); - if (start < 0) - break; - - int end = content.indexOf(".dat\">", start); - String name = content.substring(start+"href=\"routerInfo-".length(), end); - urls.add(name); - cur = end + 1; - } - - for (Iterator iter = urls.iterator(); iter.hasNext(); ) { - rv.add(fetchSeed((String)iter.next())); - } - } catch (Throwable t) { - _log.error("Error fetching routers from " + seedURL, t); - } - return rv; - } - - private RouterInfo fetchSeed(String peer) throws Exception { - URL url = new URL("http://i2p.net/i2pdb/routerInfo-" + peer + ".dat"); - if (_log.shouldLog(Log.INFO)) - _log.info("Fetching seed from " + url.toExternalForm()); - - byte data[] = readURL(url); - RouterInfo info = new RouterInfo(); - try { - info.fromByteArray(data); - return info; - } catch (DataFormatException dfe) { - _log.error("Router data at " + url.toExternalForm() + " was corrupt", dfe); - return null; - } - } - - private byte[] readURL(URL url) throws Exception { - ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); - URLConnection con = url.openConnection(); - InputStream in = con.getInputStream(); - byte buf[] = new byte[1024]; - while (true) { - int read = in.read(buf); - if (read < 0) - break; - baos.write(buf, 0, read); - } - in.close(); - return baos.toByteArray(); - } - - /** - * dump the data to the filesystem - */ - private void runExport() { - _log.info("Export"); - List peers = _monitor.getPeers(); - File exportDir = new File(_monitor.getExportDir()); - if (!exportDir.exists()) - exportDir.mkdirs(); - for (int i = 0; i < peers.size(); i++) { - String peerName = (String)peers.get(i); - PeerSummary summary = (PeerSummary)_monitor.getSummary(peerName); - FileOutputStream fos = null; - try { - File summaryFile = new File(exportDir, peerName + ".txt"); - fos = new FileOutputStream(summaryFile); - PeerSummaryWriter.getInstance().write(summary, fos); - _log.debug("Peer summary written to " + summaryFile.getAbsolutePath()); - } catch (IOException ioe) { - _log.error("Error exporting the peer summary for " + peerName, ioe); - } catch (Throwable t) { - _log.error("Unhandled exception exporting the data", t); - } finally { - if (fos != null) try { fos.close(); } catch (IOException ioe) {} - } - } - } - - /** - * Read in all the peer summaries we had previously exported, overwriting any - * existing ones in memory - * - */ - private void runImport() { - _monitor.importData(); - } - - /** - * Find all of the routers to load - * - * @return list of File objects pointing at the routers around - */ - private File[] listRouters() { - if (_monitor.getExplicitRouters() != null) { - return listRoutersExplicit(); - } else { - File dbDir = new File(_monitor.getNetDbDir()); - File files[] = dbDir.listFiles(new FilenameFilter() { - public boolean accept(File f, String name) { - return name.startsWith("routerInfo-"); - } - }); - return files; - } - } - - /** - * Get a list of router files that were explicitly specified by the netMonitor - * - */ - private File[] listRoutersExplicit() { - StringTokenizer tok = new StringTokenizer(_monitor.getExplicitRouters().trim(), ","); - List rv = new ArrayList(); - while (tok.hasMoreTokens()) { - String name = tok.nextToken(); - File cur = new File(name); - if (cur.exists()) - rv.add(cur); - } - File files[] = new File[rv.size()]; - for (int i = 0; i < rv.size(); i++) - files[i] = (File)rv.get(i); - return files; - } - - /** - * Wait the correct amount of time before harvesting again - * - */ - private void pauseHarvesting() { - try { - Thread.sleep(_monitor.getHarvestDelay()); - } catch (InterruptedException ie) {} - } -} diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerStat.java b/apps/netmonitor/java/src/net/i2p/netmonitor/PeerStat.java deleted file mode 100644 index d19e31dd2..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerStat.java +++ /dev/null @@ -1,46 +0,0 @@ -package net.i2p.netmonitor; - -/** - * Actual data point (though its not fully normalized, but KISS) - * - */ -public class PeerStat { - private String _statName; - private String _description; - private String _valueDescriptions[]; - private long _sampleDate; - private long _lvalues[]; - private double _dvalues[]; - - public PeerStat(String name, String description, String valueDescriptions[], long sampleDate, double values[]) { - this(name, description, valueDescriptions, sampleDate, null, values); - } - public PeerStat(String name, String description, String valueDescriptions[], long sampleDate, long values[]) { - this(name, description, valueDescriptions, sampleDate, values, null); - } - private PeerStat(String name, String description, String valueDescriptions[], long sampleDate, long lvalues[], double dvalues[]) { - _statName = name; - _description = description; - _valueDescriptions = valueDescriptions; - _sampleDate = sampleDate; - _lvalues = lvalues; - _dvalues = dvalues; - } - - /** unique name of the stat */ - public String getStatName() { return _statName; } - /** one line summary of the stat */ - public String getDescription() { return _description; } - /** description of each value */ - public String getValueDescription(int index) { return _valueDescriptions[index]; } - /** description of all values */ - public String[] getValueDescriptions() { return _valueDescriptions; } - /** when did the router publish the info being sampled? */ - public long getSampleDate() { return _sampleDate; } - /** if the values are integers, this contains their values */ - public long[] getLongValues() { return _lvalues; } - /** if the values are floating point numbers, this contains their values */ - public double[] getDoubleValues() { return _dvalues; } - /** are the values floating poing numbers? */ - public boolean getIsDouble() { return _dvalues != null; } -} \ No newline at end of file diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummary.java b/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummary.java deleted file mode 100644 index f2e74b9e0..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummary.java +++ /dev/null @@ -1,119 +0,0 @@ -package net.i2p.netmonitor; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -import net.i2p.util.Clock; -import net.i2p.util.Log; - -/** - * coordinate the data points summarizing the performance of a particular peer - * within the network - */ -public class PeerSummary { - private static final Log _log = new Log(PeerSummary.class); - private String _peer; - /** statName to a List of PeerStat elements (sorted by sample date, earliest first) */ - private Map _stats; - /** lock on this when accessing stat data */ - private Object _coalesceLock = new Object(); - - public PeerSummary(String peer) { - _peer = peer; - _stats = new HashMap(16); - } - - /** - * Track a data point - * - * @param stat what data are we tracking? - * @param description what does this data mean? (and what are the values?) - * @param when what data set is this sample based off? - * @param val actual data harvested - */ - public void addData(String stat, String description, String valueDescriptions[], long when, double val[]) { - synchronized (_coalesceLock) { - TreeMap stats = locked_getData(stat); - stats.put(new Long(when), new PeerStat(stat, description, valueDescriptions, when, val)); - } - } - - /** - * Track a data point - * - * @param stat what data are we tracking? - * @param description what does this data mean? (and what are the values?) - * @param when what data set is this sample based off? - * @param val actual data harvested - */ - public void addData(String stat, String description, String valueDescriptions[], long when, long val[]) { - synchronized (_coalesceLock) { - TreeMap stats = locked_getData(stat); - stats.put(new Long(when), new PeerStat(stat, description, valueDescriptions, when, val)); - } - } - - /** get the peer's name (H(routerIdentity).toBase64()) */ - public String getPeer() { return _peer; } - - /** - * fetch the ordered list of PeerStat objects for the given stat (or null if - * isn't being tracked or has no data) - * - */ - public List getData(String statName) { - synchronized (_coalesceLock) { - return new ArrayList(((TreeMap)_stats.get(statName)).values()); - } - } - - /** - * Get the names of all of the stats that are being tracked - * - */ - public Set getStatNames() { - synchronized (_coalesceLock) { - return new HashSet(_stats.keySet()); - } - } - - /** drop old data points */ - public void coalesceData(long summaryDurationMs) { - long earliest = Clock.getInstance().now() - summaryDurationMs; - synchronized (_coalesceLock) { - locked_coalesce(earliest); - } - } - - /** go through all the stats and remove ones from before the given date */ - private void locked_coalesce(long earliestSampleDate) { - if (true) return; - for (Iterator iter = _stats.keySet().iterator(); iter.hasNext(); ) { - String statName = (String)iter.next(); - TreeMap stats = (TreeMap)_stats.get(statName); - while (stats.size() > 0) { - Long when = (Long)stats.keySet().iterator().next(); - if (when.longValue() < earliestSampleDate) { - stats.remove(when); - } else { - break; - } - } - } - } - - /** - * @return PeerStat elements, ordered by sample date (earliest first) - */ - private TreeMap locked_getData(String statName) { - if (!_stats.containsKey(statName)) - _stats.put(statName, new TreeMap()); - return (TreeMap)_stats.get(statName); - } -} diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummaryReader.java b/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummaryReader.java deleted file mode 100644 index 2b67dc87a..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummaryReader.java +++ /dev/null @@ -1,106 +0,0 @@ -package net.i2p.netmonitor; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.StringTokenizer; - -import net.i2p.util.Log; - -/** - * Load up the peer summary - * - */ -class PeerSummaryReader { - private static final Log _log = new Log(PeerSummaryReader.class); - private static final PeerSummaryReader _instance = new PeerSummaryReader(); - public static final PeerSummaryReader getInstance() { return _instance; } - private PeerSummaryReader() {} - - /** */ - public void read(NetMonitor monitor, InputStream in) throws IOException { - BufferedReader reader = new BufferedReader(new InputStreamReader(in)); - String line = null; - PeerSummary summary = null; - String curDescription = null; - List curArgs = null; - try { - while ((line = reader.readLine()) != null) { - if (line.startsWith("peer\t")) { - String name = line.substring("peer\t".length()).trim(); - summary = monitor.getSummary(name); - if (summary == null) - summary = new PeerSummary(name); - } else if (line.startsWith("## ")) { - curDescription = line.substring("## ".length()).trim(); - curArgs = new ArrayList(4); - } else if (line.startsWith("# param ")) { - int start = line.indexOf(':'); - String arg = line.substring(start+1).trim(); - curArgs.add(arg); - } else { - StringTokenizer tok = new StringTokenizer(line); - String name = tok.nextToken(); - try { - long when = getTime(tok.nextToken()); - boolean isDouble = false; - List argVals = new ArrayList(curArgs.size()); - while (tok.hasMoreTokens()) { - String val = (String)tok.nextToken(); - if (val.indexOf('.') >= 0) { - argVals.add(new Double(val)); - isDouble = true; - } else { - argVals.add(new Long(val)); - } - } - String valDescriptions[] = new String[curArgs.size()]; - for (int i = 0; i < curArgs.size(); i++) - valDescriptions[i] = (String)curArgs.get(i); - if (isDouble) { - double values[] = new double[argVals.size()]; - for (int i = 0; i < argVals.size(); i++) - values[i] = ((Double)argVals.get(i)).doubleValue(); - summary.addData(name, curDescription, valDescriptions, when, values); - } else { - long values[] = new long[argVals.size()]; - for (int i = 0; i < argVals.size(); i++) - values[i] = ((Long)argVals.get(i)).longValue(); - summary.addData(name, curDescription, valDescriptions, when, values); - } - } catch (ParseException pe) { - _log.error("Error parsing the data line [" + line + "]", pe); - } catch (NumberFormatException nfe) { - _log.error("Error parsing the data line [" + line + "]", nfe); - } - } - } - } catch (Exception e) { - _log.error("Error handling the data", e); - throw new IOException("Error parsing the data"); - } - if (summary == null) - return; - summary.coalesceData(monitor.getSummaryDurationHours() * 60*60*1000); - monitor.addSummary(summary); - } - - private static final SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd.HH:mm:ss.SSS", Locale.UK); - - /** - * Converts a time (long) to text - * @param when the time to convert - * @return the textual representation - */ - public long getTime(String when) throws ParseException { - synchronized (_fmt) { - return _fmt.parse(when).getTime(); - } - } -} diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummaryWriter.java b/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummaryWriter.java deleted file mode 100644 index ba848ed94..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/PeerSummaryWriter.java +++ /dev/null @@ -1,80 +0,0 @@ -package net.i2p.netmonitor; - -import java.io.IOException; -import java.io.OutputStream; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.TreeSet; - -import net.i2p.util.Log; - -/** - * Dump various peer summaries to disk (so external apps (or good ol' vi) can - * peek into what we're harvesting - * - */ -class PeerSummaryWriter { - private static final Log _log = new Log(PeerSummaryWriter.class); - private static final PeerSummaryWriter _instance = new PeerSummaryWriter(); - public static final PeerSummaryWriter getInstance() { return _instance; } - private PeerSummaryWriter() {} - - /** write out the peer summary to the stream specified */ - public void write(PeerSummary summary, OutputStream out) throws IOException { - StringBuffer buf = new StringBuffer(4*1024); - buf.append("peer\t").append(summary.getPeer()).append('\n'); - TreeSet names = new TreeSet(summary.getStatNames()); - for (Iterator iter = names.iterator(); iter.hasNext(); ) { - String statName = (String)iter.next(); - List stats = summary.getData(statName); - for (int i = 0; i < stats.size(); i++) { - PeerStat stat = (PeerStat)stats.get(i); - if (i == 0) { - buf.append("## ").append(stat.getDescription()).append('\n'); - String descr[] = stat.getValueDescriptions(); - if (descr != null) { - for (int j = 0; j < descr.length; j++) - buf.append("# param ").append(j).append(": ").append(descr[j]).append('\n'); - } - } - buf.append(statName).append('\t'); - buf.append(getTime(stat.getSampleDate())).append('\t'); - - if (stat.getIsDouble()) { - double vals[] = stat.getDoubleValues(); - if (vals != null) { - for (int j = 0; j < vals.length; j++) - buf.append(vals[j]).append('\t'); - } - } else { - long vals[] = stat.getLongValues(); - if (vals != null) { - for (int j = 0; j < vals.length; j++) - buf.append(vals[j]).append('\t'); - } - } - buf.append('\n'); - } - } - String data = buf.toString(); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Stat: \n" + data); - out.write(data.getBytes()); - } - - private static final SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd.HH:mm:ss.SSS", Locale.UK); - - /** - * Converts a time (long) to text - * @param when the time to convert - * @return the textual representation - */ - public String getTime(long when) { - synchronized (_fmt) { - return _fmt.format(new Date(when)); - } - } -} \ No newline at end of file diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/StatGroup.java b/apps/netmonitor/java/src/net/i2p/netmonitor/StatGroup.java deleted file mode 100644 index dcf9e5817..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/StatGroup.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.i2p.netmonitor; - -import java.util.ArrayList; -import java.util.List; - -/** - * Stupid little structure to configure the DataHarvester's gathering of statistics. - * - */ -public class StatGroup { - private String _groupDescription; - private List _stats; - - public StatGroup(String description) { - _groupDescription = description; - _stats = new ArrayList(); - } - - public String getDescription() { return _groupDescription; } - public int getStatCount() { return _stats.size(); } - public StatDescription getStat(int index) { return (StatDescription)_stats.get(index); } - public void addStat(String description, String optionName, int optionField) { - StatDescription descr = new StatDescription(description, optionName, optionField); - _stats.add(descr); - } - - public class StatDescription { - private String _statDescription; - private String _optionName; - private int _optionField; - - public StatDescription(String descr, String optionName, int optionField) { - _statDescription = descr; - _optionName = optionName; - _optionField = optionField; - } - - /** brief description of this data point */ - public String getStatDescription() { return _statDescription; } - /** - * if this is harvested from the RouterInfo's options, this specifies - * which key in that map to pull from (or null if it isn't harvested - * from there) - */ - public String getOptionName() { return _optionName; } - /** - * if this is harvested from the RouterInfo's options, this specifies - * which field in value of that map to pull from (or -1 if it isn't harvested - * from there) - */ - public int getOptionField() { return _optionField; } - } -} \ No newline at end of file diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/StatGroupLoader.java b/apps/netmonitor/java/src/net/i2p/netmonitor/StatGroupLoader.java deleted file mode 100644 index 1b777f209..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/StatGroupLoader.java +++ /dev/null @@ -1,93 +0,0 @@ -package net.i2p.netmonitor; - - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import net.i2p.util.Log; - -/** - * Load up the StatGroups from the location specified to configure the data harvester. - * The stat groups are formatted in a simple properties file style, e.g.:

- * # dropped jobs
- * statGroup.0.name=droppedJobs
- * statGroup.0.detail.0.name=num dropped jobs (minute)
- * statGroup.0.detail.0.option=stat_jobQueue.droppedJobs.60m
- * statGroup.0.detail.0.field=3
- * statGroup.0.detail.1.name=num dropped jobs (hour)
- * statGroup.0.detail.1.option=stat_jobQueue.droppedJobs.60h
- * statGroup.0.detail.1.field=3
- * # 
- * statGroup.1.name=encryptTime
- * statGroup.1.detail.0.name=encryption time avg ms (minute)
- * statGroup.1.detail.0.option=stat_crypto.elGamal.encrypt.60s
- * statGroup.1.detail.0.field=0
- * statGroup.1.detail.1.name=num encryptions (minute)
- * statGroup.1.detail.1.option=stat_crypto.elGamal.encrypt.60s
- * statGroup.1.detail.1.field=7
- * statGroup.1.detail.2.name=encryption time avg ms (hour)
- * statGroup.1.detail.2.option=stat_crypto.elGamal.encrypt.60s
- * statGroup.1.detail.2.field=0
- * statGroup.1.detail.3.name=num encryptions (hour)
- * statGroup.1.detail.3.option=stat_crypto.elGamal.encrypt.60s
- * statGroup.1.detail.3.field=7
- * 
- */ -class StatGroupLoader { - private static final Log _log = new Log(StatGroupLoader.class); - /** - * Load a list of stat groups from the file specified - * - * @return list of StatGroup objects - */ - public static List loadStatGroups(String filename) { - _log.debug("Loading stat groups from " + filename); - FileInputStream fis = null; - File f = new File(filename); - try { - fis = new FileInputStream(f); - Properties p = new Properties(); - p.load(fis); - _log.debug("Config loaded from " + filename); - return loadStatGroups(p); - } catch (IOException ioe) { - _log.error("Error loading the stat groups from " + f.getAbsolutePath(), ioe); - return new ArrayList(); - } - } - - private static List loadStatGroups(Properties props) { - List rv = new ArrayList(8); - int groupNum = 0; - while (true) { - String description = props.getProperty("statGroup." + groupNum + ".name"); - if (description == null) break; - int detailNum = 0; - StatGroup group = new StatGroup(description); - while (true) { - String detailPrefix = "statGroup." + groupNum + ".detail." + detailNum + '.'; - String name = props.getProperty(detailPrefix + "name"); - if (name == null) break; - String option = props.getProperty(detailPrefix + "option"); - if (option == null) break; - String field = props.getProperty(detailPrefix + "field"); - if (field == null) break; - try { - int fieldNum = Integer.parseInt(field); - group.addStat(name, option, fieldNum); - } catch (NumberFormatException nfe) { - _log.warn("Unable to parse the field number from [" + field + "]", nfe); - break; - } - detailNum++; - } - rv.add(group); - groupNum++; - } - return rv; - } -} \ No newline at end of file diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/JFreeChartAdapter.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/JFreeChartAdapter.java deleted file mode 100644 index 95a26e4ce..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/JFreeChartAdapter.java +++ /dev/null @@ -1,109 +0,0 @@ -package net.i2p.netmonitor.gui; - -import java.awt.Color; -import java.awt.Font; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.DateAxis; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.plot.Plot; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.renderer.XYItemRenderer; -import org.jfree.chart.renderer.XYLineAndShapeRenderer; -import org.jfree.data.XYSeries; -import org.jfree.data.XYSeriesCollection; - -import net.i2p.netmonitor.PeerStat; -import net.i2p.util.Log; - -class JFreeChartAdapter { - private final static Log _log = new Log(JFreeChartAdapter.class); - private final static Color WHITE = new Color(255, 255, 255); - - ChartPanel createPanel(NetViewer state) { - ChartPanel panel = new ChartPanel(createChart(state)); - panel.setDisplayToolTips(true); - panel.setEnforceFileExtensions(true); - panel.setHorizontalZoom(true); - panel.setVerticalZoom(true); - panel.setMouseZoomable(true, true); - panel.getChart().setBackgroundPaint(WHITE); - return panel; - } - - JFreeChart createChart(NetViewer state) { - Plot plot = createPlot(state); - JFreeChart chart = new JFreeChart("I2P network performance", Font.getFont("arial"), plot, true); - return chart; - } - - void updateChart(ChartPanel panel, NetViewer state) { - XYPlot plot = (XYPlot)panel.getChart().getPlot(); - plot.setDataset(getCollection(state)); - } - - Plot createPlot(NetViewer state) { - XYItemRenderer renderer = new XYLineAndShapeRenderer(); // new XYDotRenderer(); // - XYPlot plot = new XYPlot(getCollection(state), new DateAxis(), new NumberAxis("val"), renderer); - return plot; - } - - XYSeriesCollection getCollection(NetViewer state) { - XYSeriesCollection col = new XYSeriesCollection(); - if (state != null) { - List names = state.getConfigNames(); - for (int i = 0; i < names.size(); i++) { - addPeer(col, state.getConfig((String)names.get(i))); - } - } else { - XYSeries series = new XYSeries("latency", false, false); - series.add(System.currentTimeMillis(), 0); - col.addSeries(series); - } - return col; - } - - void addPeer(XYSeriesCollection col, PeerPlotConfig config) { - Set statNames = config.getSummary().getStatNames(); - for (Iterator iter = statNames.iterator(); iter.hasNext(); ) { - String statName = (String)iter.next(); - List statData = config.getSummary().getData(statName); - if (statData.size() > 0) { - PeerStat data = (PeerStat)statData.get(0); - String args[] = data.getValueDescriptions(); - if (args != null) { - for (int i = 0; i < args.length; i++) { - if (config.getSeriesConfig().getShouldPlotValue(statName, args[i], false)) - addLine(col, config.getPeerName(), statName, args[i], statData); - } - } - } - } - } - - /** - */ - void addLine(XYSeriesCollection col, String peer, String statName, String argName, List dataPoints) { - XYSeries series = new XYSeries(peer.substring(0, 4) + ": " + argName, false, false); - for (int i = 0; i < dataPoints.size(); i++) { - PeerStat data = (PeerStat)dataPoints.get(i); - String argNames[] = data.getValueDescriptions(); - int argIndex = -1; - for (int j = 0; j < argNames.length; j++) { - if (argNames[j].equals(argName)) { - argIndex = j; - break; - } - } - if (data.getIsDouble()) - series.add(data.getSampleDate(), data.getDoubleValues()[argIndex]); - else - series.add(data.getSampleDate(), data.getLongValues()[argIndex]); - } - col.addSeries(series); - } -} \ No newline at end of file diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/JFreeChartHeartbeatPlotPane.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/JFreeChartHeartbeatPlotPane.java deleted file mode 100644 index 9d4a4e7f1..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/JFreeChartHeartbeatPlotPane.java +++ /dev/null @@ -1,53 +0,0 @@ -package net.i2p.netmonitor.gui; - -import java.awt.BorderLayout; -import java.awt.Dimension; - -import javax.swing.JLabel; -import javax.swing.JScrollPane; - -import org.jfree.chart.ChartPanel; - -import net.i2p.util.Log; - -/** - * Render the graph and legend - * - */ -class JFreeChartHeartbeatPlotPane extends NetViewerPlotPane { - private final static Log _log = new Log(JFreeChartHeartbeatPlotPane.class); - private ChartPanel _panel; - private JFreeChartAdapter _adapter; - - public JFreeChartHeartbeatPlotPane(NetViewerGUI gui) { - super(gui); - } - - public void stateUpdated() { - if (_panel == null) { - remove(0); // remove the dummy - - _adapter = new JFreeChartAdapter(); - _panel = _adapter.createPanel(_gui.getViewer()); - _panel.setBackground(_gui.getBackground()); - JScrollPane pane = new JScrollPane(_panel); - pane.setBackground(_gui.getBackground()); - add(pane, BorderLayout.CENTER); - } else { - _adapter.updateChart(_panel, _gui.getViewer()); - //_gui.pack(); - } - } - - protected void initializeComponents() { - // noop - setLayout(new BorderLayout()); - add(new JLabel(), BorderLayout.CENTER); - //dummy.setBackground(_gui.getBackground()); - //dummy.setPreferredSize(new Dimension(800,600)); - //add(dummy); - setPreferredSize(new Dimension(800,600)); - //add(_panel); - - } -} \ No newline at end of file diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewer.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewer.java deleted file mode 100644 index 174860b3f..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewer.java +++ /dev/null @@ -1,85 +0,0 @@ -package net.i2p.netmonitor.gui; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import net.i2p.netmonitor.NetMonitor; -import net.i2p.util.I2PThread; -import net.i2p.util.Log; - -/** - * Coordinate the visualization of the network monitor.

- * - * Usage: NetViewer [exportDir]
- * (exportDir is where the NetMonitor exports its state, "monitorData" by default) - */ -public class NetViewer { - private static final Log _log = new Log(NetViewer.class); - private NetMonitor _monitor; - private NetViewerGUI _gui; - private Map _plotConfigs; - private boolean _isClosed; - - public NetViewer() { - this(NetMonitor.EXPORT_DIR_DEFAULT); - } - public NetViewer(String dataDir) { - _monitor = new NetMonitor(); - _monitor.setExportDir(dataDir); - _isClosed = false; - _gui = new NetViewerGUI(this); - _plotConfigs = new HashMap(); - } - - public void runViewer() { - I2PThread t = new I2PThread(new NetViewerRunner(this)); - t.setName("NetViewer"); - t.setDaemon(false); - t.start(); - } - - void refreshGUI() { - _gui.stateUpdated(); - } - - void reloadData() { - _log.debug("Reloading data"); - _monitor.importData(); - refreshGUI(); - } - - public void addConfig(String peerName, PeerPlotConfig config) { - synchronized (_plotConfigs) { - _plotConfigs.put(peerName, config); - } - } - - public PeerPlotConfig getConfig(String peerName) { - synchronized (_plotConfigs) { - return (PeerPlotConfig)_plotConfigs.get(peerName); - } - } - - public List getConfigNames() { - synchronized (_plotConfigs) { - return new ArrayList(_plotConfigs.keySet()); - } - } - - public NetMonitor getMonitor() { return _monitor; } - - long getDataLoadDelay() { return _monitor.getExportDelay(); } - - /** has the viewer been closed? */ - public boolean getIsClosed() { return _isClosed; } - public void setIsClosed(boolean closed) { _isClosed = closed; } - - public static final void main(String args[]) { - if (args.length == 1) - new NetViewer(args[0]).runViewer(); - else - new NetViewer().runViewer(); - } -} \ No newline at end of file diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerCommandBar.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerCommandBar.java deleted file mode 100644 index b1b0b923b..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerCommandBar.java +++ /dev/null @@ -1,70 +0,0 @@ -package net.i2p.netmonitor.gui; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; - -import javax.swing.DefaultComboBoxModel; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; - -class NetViewerCommandBar extends JPanel { - private NetViewerGUI _gui; - private JComboBox _refreshRate; - private JTextField _location; - - /** - * Constructs a command bar onto the gui - * @param gui the gui the command bar is associated with - */ - public NetViewerCommandBar(NetViewerGUI gui) { - _gui = gui; - initializeComponents(); - } - - private void refreshChanged(ItemEvent evt) {} - private void loadCalled() { - //_gui.getMonitor().load(_location.getText()); - } - - private void browseCalled() { - JFileChooser chooser = new JFileChooser(_location.getText()); - chooser.setBackground(_gui.getBackground()); - chooser.setMultiSelectionEnabled(false); - int rv = chooser.showDialog(this, "Load"); - //if (rv == JFileChooser.APPROVE_OPTION) - // _gui.getMonitor().load(chooser.getSelectedFile().getAbsolutePath()); - } - - private void initializeComponents() { - _refreshRate = new JComboBox(new DefaultComboBoxModel(new Object[] {"10 second refresh", "30 second refresh", "1 minute refresh", "5 minute refresh"})); - _refreshRate.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent evt) { refreshChanged(evt); } }); - _refreshRate.setEnabled(false); - _refreshRate.setBackground(_gui.getBackground()); - //add(_refreshRate); - JLabel loadLabel = new JLabel("Load from: "); - loadLabel.setBackground(_gui.getBackground()); - add(loadLabel); - _location = new JTextField(20); - _location.setToolTipText("Either specify a local filename or a fully qualified URL"); - _location.setBackground(_gui.getBackground()); - _location.setEnabled(false); - add(_location); - JButton browse = new JButton("Browse..."); - browse.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { browseCalled(); } }); - browse.setBackground(_gui.getBackground()); - browse.setEnabled(false); - add(browse); - JButton load = new JButton("Load"); - load.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { loadCalled(); } }); - load.setBackground(_gui.getBackground()); - load.setEnabled(false); - add(load); - setBackground(_gui.getBackground()); - } -} \ No newline at end of file diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerControlPane.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerControlPane.java deleted file mode 100644 index 22aca39d5..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerControlPane.java +++ /dev/null @@ -1,106 +0,0 @@ -package net.i2p.netmonitor.gui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; - -import net.i2p.util.Log; - -/** - * Render the control widgets (refresh/load/snapshot and the - * tabbed panel with the plot config data) - * - */ -class NetViewerControlPane extends JPanel { - private final static Log _log = new Log(NetViewerControlPane.class); - private NetViewerGUI _gui; - private JTabbedPane _configPane; - private final static Color WHITE = new Color(255, 255, 255); - private final static Color LIGHT_BLUE = new Color(180, 180, 255); - private final static Color BLACK = new Color(0, 0, 0); - private Color _background = WHITE; - private Color _foreground = BLACK; - - /** - * Constructs a control panel onto the gui - * @param gui the gui the panel is associated with - */ - public NetViewerControlPane(NetViewerGUI gui) { - _gui = gui; - initializeComponents(); - } - - /** the settings have changed - revise */ - void refreshView() { - _gui.refreshView(); - } - - /** - * Callback: when tests have changed - */ - public synchronized void stateUpdated() { - List knownNames = new ArrayList(8); - List peers = _gui.getViewer().getMonitor().getPeers(); - _log.debug("GUI updated with peers: " + peers); - for (int i = 0; i < peers.size(); i++) { - String name = (String)peers.get(i); - String shortName = name.substring(0,4); - knownNames.add(shortName); - if (_configPane.indexOfTab(shortName) >= 0) { - JScrollPane pane = (JScrollPane)_configPane.getComponentAt(_configPane.indexOfTab(shortName)); - PeerPlotConfigPane cfgPane = (PeerPlotConfigPane)pane.getViewport().getView(); - cfgPane.stateUpdated(); - _log.debug("We already know about [" + name + "]"); - } else { - _log.info("The peer [" + name + "] is new to us"); - PeerPlotConfig cfg = new PeerPlotConfig(_gui.getViewer().getMonitor().getSummary(name)); - _gui.getViewer().addConfig(name, cfg); - PeerPlotConfigPane pane = new PeerPlotConfigPane(cfg, this); - JScrollPane p = new JScrollPane(pane); - p.setBackground(_background); - _configPane.addTab(shortName, null, p, "Peer " + name); - _configPane.setBackgroundAt(_configPane.getTabCount()-1, _background); - _configPane.setForegroundAt(_configPane.getTabCount()-1, _foreground); - } - } - List toRemove = new ArrayList(4); - for (int i = 0; i < _configPane.getTabCount(); i++) { - if (knownNames.contains(_configPane.getTitleAt(i))) { - // noop - } else { - toRemove.add(_configPane.getTitleAt(i)); - } - } - for (int i = 0; i < toRemove.size(); i++) { - String title = (String)toRemove.get(i); - _log.info("Removing peer [" + title + "]"); - _configPane.removeTabAt(_configPane.indexOfTab(title)); - } - } - - private void initializeComponents() { - if (_gui != null) - setBackground(_gui.getBackground()); - else - setBackground(_background); - setLayout(new BorderLayout()); - NetViewerCommandBar bar = new NetViewerCommandBar(_gui); - bar.setBackground(getBackground()); - add(bar, BorderLayout.NORTH); - _configPane = new JTabbedPane(JTabbedPane.LEFT); - _configPane.setBackground(_background); - JScrollPane pane = new JScrollPane(_configPane); - pane.setBackground(_background); - add(pane, BorderLayout.CENTER); - //setPreferredSize(new Dimension(800, 400)); - //setMinimumSize(new Dimension(800, 400)); - //setMaximumSize(new Dimension(800, 400)); - } - - NetViewer getViewer() { return _gui.getViewer(); } -} \ No newline at end of file diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerGUI.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerGUI.java deleted file mode 100644 index c50d45144..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerGUI.java +++ /dev/null @@ -1,105 +0,0 @@ -package net.i2p.netmonitor.gui; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; - -class NetViewerGUI extends JFrame { - private NetViewer _viewer; - private NetViewerPlotPane _plotPane; - private NetViewerControlPane _controlPane; - private final static Color WHITE = new Color(255, 255, 255); - private Color _background = WHITE; - - /** - * Creates the GUI for all youz who be too shoopid for text based shitz - * @param monitor the monitor the gui operates over - */ - public NetViewerGUI(NetViewer viewer) { - super("Network Viewer"); - _viewer = viewer; - initializeComponents(); - pack(); - //setResizable(false); - setVisible(true); - } - - NetViewer getViewer() { return _viewer; } - - /** build up all our widgets */ - private void initializeComponents() { - getContentPane().setLayout(new BorderLayout()); - - setBackground(_background); - - _plotPane = new JFreeChartHeartbeatPlotPane(this); // // new NetViewerPlotPane(this); // - _plotPane.setBackground(_background); - JScrollPane pane = new JScrollPane(_plotPane); - pane.setBackground(_background); - //getContentPane().add(pane, BorderLayout.CENTER); - - _controlPane = new NetViewerControlPane(this); - _controlPane.setBackground(_background); - //getContentPane().add(_controlPane, BorderLayout.SOUTH); - - JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT, _plotPane, _controlPane); - //split.setDividerLocation(0.3d); - getContentPane().add(split, BorderLayout.CENTER); - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - initializeMenus(); - } - - /** - * Callback: when the state of the world changes . . . - */ - public void stateUpdated() { - _controlPane.stateUpdated(); - _plotPane.stateUpdated(); - //pack(); - } - - public void refreshView() { - _plotPane.stateUpdated(); - } - - private void exitCalled() { - _viewer.setIsClosed(true); - setVisible(false); - System.exit(0); - } - private void loadConfigCalled() {} - private void saveConfigCalled() {} - private void loadSnapshotCalled() {} - private void saveSnapshotCalled() {} - - private void initializeMenus() { - JMenuBar bar = new JMenuBar(); - JMenu fileMenu = new JMenu("File"); - JMenuItem loadConfig = new JMenuItem("Load config"); - loadConfig.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { loadConfigCalled(); } }); - JMenuItem saveConfig = new JMenuItem("Save config"); - saveConfig.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { saveConfigCalled(); } }); - JMenuItem saveSnapshot = new JMenuItem("Save snapshot"); - saveSnapshot.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { saveSnapshotCalled(); } }); - JMenuItem loadSnapshot = new JMenuItem("Load snapshot"); - loadSnapshot.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { loadSnapshotCalled(); } }); - JMenuItem exit = new JMenuItem("Exit"); - exit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { exitCalled(); } }); - - fileMenu.add(loadConfig); - fileMenu.add(saveConfig); - fileMenu.add(loadSnapshot); - fileMenu.add(saveSnapshot); - fileMenu.add(exit); - bar.add(fileMenu); - setJMenuBar(bar); - } -} \ No newline at end of file diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerPlotPane.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerPlotPane.java deleted file mode 100644 index 321698d0c..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerPlotPane.java +++ /dev/null @@ -1,46 +0,0 @@ -package net.i2p.netmonitor.gui; - -import javax.swing.JPanel; -import javax.swing.JTextArea; - -import net.i2p.util.Log; - -/** - * Render the graph and legend - */ -class NetViewerPlotPane extends JPanel { - private final static Log _log = new Log(NetViewerPlotPane.class); - protected NetViewerGUI _gui; - private JTextArea _text; - - /** - * Constructs the plot pane - * @param gui the gui the pane is attached to - */ - public NetViewerPlotPane(NetViewerGUI gui) { - _gui = gui; - initializeComponents(); - } - - /** - * Callback: when things change . . . - */ - public void stateUpdated() { - StringBuffer buf = new StringBuffer(32*1024); - buf.append("moo"); - _text.setText(buf.toString()); - } - - protected void initializeComponents() { - setBackground(_gui.getBackground()); - //Dimension size = new Dimension(800, 600); - _text = new JTextArea("",30,80); // 16, 60); - _text.setAutoscrolls(true); - _text.setEditable(false); - // _text.setLineWrap(true); - // add(new JScrollPane(_text)); - add(_text); - // add(new JScrollPane(_text, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS)); - // setPreferredSize(size); - } -} \ No newline at end of file diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerRunner.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerRunner.java deleted file mode 100644 index 2917e14ee..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/NetViewerRunner.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.i2p.netmonitor.gui; - -class NetViewerRunner implements Runnable { - private NetViewer _viewer; - - public NetViewerRunner(NetViewer viewer) { - _viewer = viewer; - } - - public void run() { - while (!_viewer.getIsClosed()) { - _viewer.reloadData(); - try { Thread.sleep(_viewer.getDataLoadDelay()*1000); } catch (InterruptedException ie) {} - } - } -} \ No newline at end of file diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/PeerPlotConfig.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/PeerPlotConfig.java deleted file mode 100644 index fafbd22b9..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/PeerPlotConfig.java +++ /dev/null @@ -1,213 +0,0 @@ -package net.i2p.netmonitor.gui; - -import java.awt.Color; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -import net.i2p.netmonitor.PeerSummary; -import net.i2p.util.Log; - -/** - * Configure how we want to render a particular peerSummary in the GUI - */ -class PeerPlotConfig { - private final static Log _log = new Log(PeerPlotConfig.class); - /** where can we find the current state/data (either as a filename or a URL)? */ - private String _location; - /** what test are we defining the plot data for? */ - private PeerSummary _summary; - /** how should we render the current data set? */ - private PlotSeriesConfig _seriesConfig; - private Set _listeners; - private boolean _disabled; - - /** - * Delegating constructor . . . - * @param location the name of the file/URL to get the data from - */ - public PeerPlotConfig(String location) { - this(location, null, null); - } - - /** - * Delegating constructor . . . - * @param location the name of the file/URL to get the data from - */ - public PeerPlotConfig(PeerSummary summary) { - this(null, summary, null); - } - - /** - * Constructs a config =) - * @param location the location of the file/URL to get the data from - * @param config the client's configuration - * @param seriesConfig the series config - */ - public PeerPlotConfig(String location, PeerSummary summary, PlotSeriesConfig seriesConfig) { - _location = location; - _summary = summary; - if (seriesConfig != null) - _seriesConfig = seriesConfig; - else - _seriesConfig = new PlotSeriesConfig(); - - _listeners = Collections.synchronizedSet(new HashSet(2)); - _disabled = false; - } - - /** - * Where is the current state data supposed to be found? This must either be a - * local file path or a URL - * @return the current location - */ - public String getLocation() { return _location; } - - /** - * The location the current state data is supposed to be found. This must either be - * a local file path or a URL - * @param location the location - */ - public void setLocation(String location) { - _location = location; - fireUpdate(); - } - - /** - * What are we configuring? - * @return the client configuration - */ - public PeerSummary getSummary() { return _summary; } - - /** - * Sets what we are currently configuring - * @param config the new config - */ - public void setPeerSummary(PeerSummary summary) { - _summary = summary; - fireUpdate(); - } - - /** - * How do we want to render the current data set? - * @return the way we currently render the data - */ - public PlotSeriesConfig getSeriesConfig() { return _seriesConfig; } - - /** - * Sets how we want to render the current data set. - * @param config the new config - */ - public void setSeriesConfig(PlotSeriesConfig config) { - _seriesConfig = config; - fireUpdate(); - } - - /** - * four char description of the peer - * @return the name - */ - public String getPeerName() { return _summary.getPeer(); } - - /** - * we've got someone who wants to be notified of changes to the plot config - * @param lsnr the listener to be added - */ - public void addListener(UpdateListener lsnr) { _listeners.add(lsnr); } - - /** - * remove a listener - * @param lsnr the listener to remove - */ - public void removeListener(UpdateListener lsnr) { _listeners.remove(lsnr); } - - void fireUpdate() { - if (_disabled) return; - for (Iterator iter = _listeners.iterator(); iter.hasNext(); ) { - ((UpdateListener)iter.next()).configUpdated(this); - } - } - - /** - * Disables notification of events listeners - * @see PeerPlotConfig#fireUpdate() - */ - public void disableEvents() { _disabled = true; } - - /** - * Enables notification of events listeners - * @see PeerPlotConfig#fireUpdate() - */ - public void enableEvents() { _disabled = false; } - - /** - * How do we want to render a particular dataset (either the current or the averaged values)? - */ - public class PlotSeriesConfig { - private Map _shouldPlot; - private Map _plotColors; - - /** - * Creates a config for the rendering of a particular dataset) - * @param plotLost do we plot lost packets? - * @param plotColor in what color? - */ - public PlotSeriesConfig() { - _shouldPlot = new HashMap(16); - _plotColors = new HashMap(16); - } - - /** - * Retrieves the plot config this plot series config is a part of - * @return the plot config - */ - public PeerPlotConfig getPlotConfig() { return PeerPlotConfig.this; } - - public boolean getShouldPlotValue(String statName, String argName, boolean defaultVal) { - Boolean val = (Boolean)_shouldPlot.get(statName + argName); - if (val == null) - return defaultVal; - else - return val.booleanValue(); - } - - public void setShouldPlotValue(String statName, String argName, boolean shouldPlot) { - _shouldPlot.put(statName + argName, new Boolean(shouldPlot)); - fireUpdate(); - } - - /** - * What color should we plot the data with? - * @return the color - */ - public Color getPlotLineColor(String statName, String argName) { - return (Color)_plotColors.get(statName + argName); - } - - /** - * Sets the color we should plot the data with - * @param color the color to use - */ - public void setPlotLineColor(String statName, String argName, Color color) { - if (color == null) - _plotColors.remove(statName + argName); - else - _plotColors.put(statName + argName, color); - fireUpdate(); - } - } - - /** - * An interface for listening to updates . . . - */ - public interface UpdateListener { - /** - * @param config the peer plot config that changes - * @see PeerPlotConfig#fireUpdate() - */ - void configUpdated(PeerPlotConfig config); - } -} \ No newline at end of file diff --git a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/PeerPlotConfigPane.java b/apps/netmonitor/java/src/net/i2p/netmonitor/gui/PeerPlotConfigPane.java deleted file mode 100644 index 864fd1be8..000000000 --- a/apps/netmonitor/java/src/net/i2p/netmonitor/gui/PeerPlotConfigPane.java +++ /dev/null @@ -1,276 +0,0 @@ -package net.i2p.netmonitor.gui; - -import java.awt.Color; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Random; -import java.util.Set; -import java.util.TreeMap; - -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; - -import net.i2p.netmonitor.PeerStat; -import net.i2p.util.Log; - -class PeerPlotConfigPane extends JPanel implements PeerPlotConfig.UpdateListener { - private final static Log _log = new Log(PeerPlotConfigPane.class); - private PeerPlotConfig _config; - private NetViewerControlPane _parent; - private JLabel _peer; - private JButton _toggleAll; - private OptionGroup _options[]; - private Random _rnd = new Random(); - private final static Color WHITE = new Color(255, 255, 255); - private Color _background = WHITE; - - /** - * Constructs a pane - * @param config the plot config it represents - * @param pane the pane this one is attached to - */ - public PeerPlotConfigPane(PeerPlotConfig config, NetViewerControlPane pane) { - _config = config; - _parent = pane; - if (_parent != null) - _background = _parent.getBackground(); - _config.addListener(this); - initializeComponents(); - } - - private void initializeComponents() { - buildComponents(); - placeComponents(this); - refreshView(); - //setBorder(new BevelBorder(BevelBorder.RAISED)); - setBackground(_background); - } - - /** - * place all the gui components onto the given panel - * @param body the panel to place the components on - */ - private void placeComponents(JPanel body) { - body.setLayout(new GridBagLayout()); - GridBagConstraints cts = new GridBagConstraints(); - - // row 0: peer name + toggle All - cts.gridx = 0; - cts.gridy = 0; - cts.gridwidth = 2; - cts.anchor = GridBagConstraints.WEST; - cts.fill = GridBagConstraints.NONE; - body.add(_peer, cts); - cts.gridx = 2; - cts.gridy = 0; - cts.gridwidth = 1; - cts.anchor = GridBagConstraints.EAST; - cts.fill = GridBagConstraints.NONE; - body.add(_toggleAll, cts); - - int row = 0; - for (int i = 0; i < _options.length; i++) { - row++; - cts.gridx = 0; - cts.gridy = row; - cts.gridwidth = 3; - cts.weightx = 5; - cts.fill = GridBagConstraints.BOTH; - cts.anchor = GridBagConstraints.WEST; - body.add(_options[i]._statName, cts); - - for (int j = 0; j < _options[i]._statAttributes.size(); j++) { - row++; - cts.gridx = 0; - cts.gridy = row; - cts.gridwidth = 1; - cts.weightx = 1; - cts.fill = GridBagConstraints.NONE; - body.add(new JLabel(" "), cts); - cts.gridx = 1; - cts.gridy = row; - cts.gridwidth = 1; - cts.weightx = 5; - cts.fill = GridBagConstraints.BOTH; - JCheckBox box = (JCheckBox)_options[i]._statAttributes.get(j); - box.setBackground(_background); - body.add(box, cts); - cts.gridx = 2; - cts.fill = GridBagConstraints.NONE; - cts.anchor = GridBagConstraints.EAST; - JButton toggleAttr = new JButton("Toggle all"); - toggleAttr.setBackground(_background); - toggleAttr.addActionListener(new ToggleAttribute(_options[i].getStatName(), box.getText(), box)); - body.add(toggleAttr, cts); - } - } - } - - private class ToggleAttribute implements ActionListener { - private String _statName; - private String _attrName; - private JCheckBox _box; - public ToggleAttribute(String statName, String attrName, JCheckBox box) { - _statName = statName; - _attrName = attrName; - _box = box; - } - public void actionPerformed(ActionEvent evt) { - boolean setActive = true; - if (_box.isSelected()) { - setActive = false; - } - - List names = _parent.getViewer().getConfigNames(); - for (int i = 0; i < names.size(); i++) { - String name = (String)names.get(i); - PeerPlotConfig cfg = _parent.getViewer().getConfig(name); - cfg.getSeriesConfig().setShouldPlotValue(_statName, _attrName, setActive); - _log.debug("Setting " + _statName + "." + _attrName + " to " + setActive + " for " + name); - } - _parent.stateUpdated(); - _parent.refreshView(); - } - } - - /** build all of the gui components */ - private void buildComponents() { - _peer = new JLabel("Router: " + _config.getPeerName()); - - _toggleAll = new JButton("Show all"); - _toggleAll.setBackground(_background); - _toggleAll.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { - _config.disableEvents(); - for (int i = 0; i < _options.length; i++) { - for (int j = 0; j < _options[i]._statAttributes.size(); j++) { - JCheckBox box = (JCheckBox)_options[i]._statAttributes.get(j); - String statName = _options[i].getStatName(); - String attrName = box.getText(); - if (_toggleAll.getText().equals("Show all")) { - box.setSelected(true); - _config.getSeriesConfig().setShouldPlotValue(statName, attrName, true); - } else { - box.setSelected(false); - _config.getSeriesConfig().setShouldPlotValue(statName, attrName, false); - } - } - } - if (_toggleAll.getText().equals("Show all")) - _toggleAll.setText("Hide all"); - else - _toggleAll.setText("Show all"); - _config.enableEvents(); - _config.fireUpdate(); - } - }); - - Set statNames = _config.getSummary().getStatNames(); - List options = new ArrayList(statNames.size()); - for (Iterator iter = statNames.iterator(); iter.hasNext(); ) { - String statName = (String)iter.next(); - List data = _config.getSummary().getData(statName); - if ( (data != null) && (data.size() > 0) ) { - PeerStat stat = (PeerStat)data.get(0); - String attributes[] = stat.getValueDescriptions(); - OptionGroup group = new OptionGroup(statName, attributes); - options.add(group); - } - } - TreeMap orderedOptions = new TreeMap(); - for (int i = 0; i < options.size(); i++) { - OptionGroup grp = (OptionGroup)options.get(i); - orderedOptions.put(grp.getStatName(), grp); - } - _options = new OptionGroup[options.size()]; - int i = 0; - for (Iterator iter = orderedOptions.values().iterator(); iter.hasNext(); ) { - OptionGroup grp = (OptionGroup)iter.next(); - _options[i] = grp; - i++; - } - } - - /** the settings have changed - revise */ - private void refreshView() { - _parent.refreshView(); - } - - /** - * notified that the config has been updated - * @param config the config that was been updated - */ - public void configUpdated(PeerPlotConfig config) { refreshView(); } - - public void stateUpdated() { - for (int i = 0; i < _options.length; i++) { - for (int j = 0; j < _options[i]._statAttributes.size(); j++) { - JCheckBox box = (JCheckBox)_options[i]._statAttributes.get(j); - if (_config.getSeriesConfig().getShouldPlotValue(_options[i].getStatName(), box.getText(), false)) - box.setSelected(true); - else - box.setSelected(false); - } - } - } - - private class OptionGroup { - JTextField _statName; - List _statAttributes; - - public String getStatName() { return _statName.getText(); } - - /** - * Creates an OptionLine. - * @param statName statistic group in question - * @param statAttributes list of attributes we keep about this stat - */ - public OptionGroup(String statName, String statAttributes[]) { - _statName = new JTextField(statName); - _statName.setEditable(false); - _statName.setBackground(_background); - _statAttributes = new ArrayList(4); - if (statAttributes != null) { - for (int i = 0; i < statAttributes.length; i++) { - JCheckBox box = new JCheckBox(statAttributes[i]); - box.addActionListener(new UpdateListener(OptionGroup.this)); - _statAttributes.add(box); - } - } - } - } - - private class UpdateListener implements ActionListener { - private OptionGroup _group; - - /** - * Update Listener constructor . . . - * @param group the group of stats to watch - */ - public UpdateListener(OptionGroup group) { - _group = group; - } - - /* (non-Javadoc) - * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) - */ - public void actionPerformed(ActionEvent evt) { - _config.disableEvents(); - - for (int i = 0; i < _group._statAttributes.size(); i++) { - JCheckBox box = (JCheckBox)_group._statAttributes.get(i); - _config.getSeriesConfig().setShouldPlotValue(_group.getStatName(), box.getText(), box.isSelected()); - } - _config.enableEvents(); - _config.fireUpdate(); - } - } -} \ No newline at end of file diff --git a/apps/phttprelay/doc/readme.license.txt b/apps/phttprelay/doc/readme.license.txt deleted file mode 100644 index 18f90e09b..000000000 --- a/apps/phttprelay/doc/readme.license.txt +++ /dev/null @@ -1,10 +0,0 @@ -$Id$ - -the i2p/apps/phttprelay module is the root of the -PHTTPRelay application, and everything within it -is released according to the terms of the I2P -license policy. That means everything contained -within the i2p/apps/phttprelay module is released -into the public domain unless otherwise marked. -Alternate licenses that may be used include BSD, -Cryptix, and MIT. diff --git a/apps/phttprelay/java/build.xml b/apps/phttprelay/java/build.xml deleted file mode 100644 index 6d924a2a2..000000000 --- a/apps/phttprelay/java/build.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/phttprelay/java/lib/LICENSE.html b/apps/phttprelay/java/lib/LICENSE.html deleted file mode 100644 index 678cdec53..000000000 --- a/apps/phttprelay/java/lib/LICENSE.html +++ /dev/null @@ -1,159 +0,0 @@ - - - Jetty License - - - -

Jetty License
-
$Revision: 1.1 $
- -Preamble:

- -The intent of this document is to state the conditions under which the -Jetty Package may be copied, such that the Copyright Holder maintains some -semblance of control over the development of the package, while giving the -users of the package the right to use, distribute and make reasonable -modifications to the Package in accordance with the goals and ideals of -the Open Source concept as described at -http://www.opensource.org. -

-It is the intent of this license to allow commercial usage of the Jetty -package, so long as the source code is distributed or suitable visible -credit given or other arrangements made with the copyright holders. - -

Definitions:

- -

    -
  • "Jetty" refers to the collection of Java classes that are - distributed as a HTTP server with servlet capabilities and - associated utilities.

    - -

  • "Package" refers to the collection of files distributed by the - Copyright Holder, and derivatives of that collection of files - created through textual modification.

    - -

  • "Standard Version" refers to such a Package if it has not been - modified, or has been modified in accordance with the wishes - of the Copyright Holder.

    - -

  • "Copyright Holder" is whoever is named in the copyright or - copyrights for the package.
    - Mort Bay Consulting Pty. Ltd. (Australia) is the "Copyright - Holder" for the Jetty package.

    - -

  • "You" is you, if you're thinking about copying or distributing - this Package.

    - -

  • "Reasonable copying fee" is whatever you can justify on the - basis of media cost, duplication charges, time of people involved, - and so on. (You will not be required to justify it to the - Copyright Holder, but only to the computing community at large - as a market that must bear the fee.)

    - -

  • "Freely Available" means that no fee is charged for the item - itself, though there may be fees involved in handling the item. - It also means that recipients of the item may redistribute it - under the same conditions they received it.

    -

- -0. The Jetty Package is Copyright (c) Mort Bay Consulting Pty. Ltd. -(Australia) and others. Individual files in this package may contain -additional copyright notices. The javax.servlet packages are copyright -Sun Microsystems Inc.

- -1. The Standard Version of the Jetty package is -available from http://jetty.mortbay.org.

- -2. You may make and distribute verbatim copies of the source form -of the Standard Version of this Package without restriction, provided that -you include this license and all of the original copyright notices -and associated disclaimers.

- -3. You may make and distribute verbatim copies of the compiled form of the -Standard Version of this Package without restriction, provided that you -include this license.

- -4. You may apply bug fixes, portability fixes and other modifications -derived from the Public Domain or from the Copyright Holder. A Package -modified in such a way shall still be considered the Standard Version.

- -5. You may otherwise modify your copy of this Package in any way, provided -that you insert a prominent notice in each changed file stating how and -when you changed that file, and provided that you do at least ONE of the -following:

- -

-a) Place your modifications in the Public Domain or otherwise make them -Freely Available, such as by posting said modifications to Usenet or -an equivalent medium, or placing the modifications on a major archive -site such as ftp.uu.net, or by allowing the Copyright Holder to include -your modifications in the Standard Version of the Package.

- -b) Use the modified Package only within your corporation or organization.

- -c) Rename any non-standard classes so the names do not conflict -with standard classes, which must also be provided, and provide -a separate manual page for each non-standard class that clearly -documents how it differs from the Standard Version.

- -d) Make other arrangements with the Copyright Holder.

-

- -6. You may distribute modifications or subsets of this Package in source -code or compiled form, provided that you do at least ONE of the following:

- -

-a) Distribute this license and all original copyright messages, together -with instructions (in the about dialog, manual page or equivalent) on where -to get the complete Standard Version.

- -b) Accompany the distribution with the machine-readable source of -the Package with your modifications. The modified package must include -this license and all of the original copyright notices and associated -disclaimers, together with instructions on where to get the complete -Standard Version.

- -c) Make other arrangements with the Copyright Holder.

-

- -7. You may charge a reasonable copying fee for any distribution of this -Package. You may charge any fee you choose for support of this Package. -You may not charge a fee for this Package itself. However, -you may distribute this Package in aggregate with other (possibly -commercial) programs as part of a larger (possibly commercial) software -distribution provided that you meet the other distribution requirements -of this license.

- -8. Input to or the output produced from the programs of this Package -do not automatically fall under the copyright of this Package, but -belong to whomever generated them, and may be sold commercially, and -may be aggregated with this Package.

- -9. Any program subroutines supplied by you and linked into this Package -shall not be considered part of this Package.

- -10. The name of the Copyright Holder may not be used to endorse or promote -products derived from this software without specific prior written -permission.

- -11. This license may change with each release of a Standard Version of -the Package. You may choose to use the license associated with version -you are using or the license of the latest Standard Version.

- -12. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

- -13. If any superior law implies a warranty, the sole remedy under such shall -be , at the Copyright Holders option either a) return of any price paid or -b) use or reasonable endeavours to repair or replace the software.

- -14. This license shall be read under the laws of Australia.

- -

The End
- -
This license was derived from the Artistic license published -on http://www.opensource.com
-
- - diff --git a/apps/phttprelay/java/lib/javax.servlet.jar b/apps/phttprelay/java/lib/javax.servlet.jar deleted file mode 100644 index 6bee0cc32..000000000 Binary files a/apps/phttprelay/java/lib/javax.servlet.jar and /dev/null differ diff --git a/apps/phttprelay/java/lib/readme.txt b/apps/phttprelay/java/lib/readme.txt deleted file mode 100644 index d16d9e679..000000000 --- a/apps/phttprelay/java/lib/readme.txt +++ /dev/null @@ -1,6 +0,0 @@ -The file javax.servlet.jar is distributed under the terms of LICENSE.html, -which is the implementation of the java servlet classes as retrieved from -http://jetty.mortbay.org/jetty/ - -It is only included to assist in building the phttprelay.war file on hosts -that do not have a servlet container / implementation. diff --git a/apps/phttprelay/java/src/net/i2p/phttprelay/CheckSendStatusServlet.java b/apps/phttprelay/java/src/net/i2p/phttprelay/CheckSendStatusServlet.java deleted file mode 100644 index b7c2af1b9..000000000 --- a/apps/phttprelay/java/src/net/i2p/phttprelay/CheckSendStatusServlet.java +++ /dev/null @@ -1,114 +0,0 @@ -package net.i2p.phttprelay; - -/* - * free (adj.): unencumbered; not under the control of others - * Written by jrandom in 2003 and released into the public domain - * with no warranty of any kind, either expressed or implied. - * It probably won't make your computer catch on fire, or eat - * your children, but it might. Use at your own risk. - * - */ - -import java.io.File; -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * Check the status of previous message delivery, returning either pending or - * unknown, where pending means that particular message ID for that particular - * target is still on the server, and unknown means it has either not been created - * or it has been sent successfully. It does this by sending HTTP 204 (NO CONTENT) - * for pending, and HTTP 404 (NOT FOUND) for unknown.

- * - * This servlet should be set up in web.xml as follows: - * - * - * CheckSendStatus - * net.i2p.phttprelay.CheckSendStatusServlet - * - * baseDir - * /usr/local/jetty/phttprelayDir - * - * - * - * - * CheckSendStatus - * /phttpCheckSendStatus - * - * - * baseDir is the directory under which registrants and their pending messages are stored - * - */ -public class CheckSendStatusServlet extends PHTTPRelayServlet { - /* URL parameters on the check */ - - /** H(routerIdent).toBase64() of the target to receive the message */ - public final static String PARAM_SEND_TARGET = "target"; - /** msgId parameter */ - public final static String PARAM_MSG_ID = "msgId"; - - public final static String PROP_STATUS = "status"; - public final static String STATUS_PENDING = "pending"; - public final static String STATUS_UNKNOWN = "unknown"; - - public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - String target = req.getParameter(PARAM_SEND_TARGET); - String msgIdStr = req.getParameter(PARAM_MSG_ID); - - log("Checking status of [" + target + "] message [" + msgIdStr + "]"); - if (!isKnownMessage(target, msgIdStr)) { - log("Not known - its not pending"); - notPending(req, resp); - return; - } else { - log("Known - its still pending"); - pending(req, resp); - return; - } - } - - private boolean isKnownMessage(String target, String msgId) throws IOException { - if ((target == null) || (target.trim().length() <= 0)) return false; - if ((msgId == null) || (msgId.trim().length() <= 0)) return false; - File identDir = getIdentDir(target); - if (identDir.exists()) { - File identFile = new File(identDir, "identity.dat"); - if (identFile.exists()) { - // known and valid (maybe we need to check the file format... naw, fuck it - File msgFile = new File(identDir, "msg" + msgId + ".dat"); - if (msgFile.exists()) - return true; - else - return false; - } else { - return false; - } - } else { - return false; - } - } - - private void pending(HttpServletRequest req, HttpServletResponse resp) throws IOException { - resp.setStatus(HttpServletResponse.SC_OK); - ServletOutputStream out = resp.getOutputStream(); - StringBuffer buf = new StringBuffer(); - buf.append(PROP_STATUS).append('=').append(STATUS_PENDING).append('\n'); - out.write(buf.toString().getBytes()); - out.flush(); - out.close(); - } - - private void notPending(HttpServletRequest req, HttpServletResponse resp) throws IOException { - resp.setStatus(HttpServletResponse.SC_OK); - ServletOutputStream out = resp.getOutputStream(); - StringBuffer buf = new StringBuffer(); - buf.append(PROP_STATUS).append('=').append(STATUS_UNKNOWN).append('\n'); - out.write(buf.toString().getBytes()); - out.flush(); - out.close(); - } -} \ No newline at end of file diff --git a/apps/phttprelay/java/src/net/i2p/phttprelay/LockManager.java b/apps/phttprelay/java/src/net/i2p/phttprelay/LockManager.java deleted file mode 100644 index 433203169..000000000 --- a/apps/phttprelay/java/src/net/i2p/phttprelay/LockManager.java +++ /dev/null @@ -1,44 +0,0 @@ -package net.i2p.phttprelay; - -/* - * free (adj.): unencumbered; not under the control of others - * Written by jrandom in 2003 and released into the public domain - * with no warranty of any kind, either expressed or implied. - * It probably won't make your computer catch on fire, or eat - * your children, but it might. Use at your own risk. - * - */ - -import java.util.HashSet; -import java.util.Set; - -/** - * Lock identities for updating messages (so that they aren't read / deleted - * while being written) - * - */ -class LockManager { - private volatile static Set _locks = new HashSet(); // target - - public static void lockIdent(String target) { - while (true) { - synchronized (_locks) { - if (!_locks.contains(target)) { - _locks.add(target); - return; - } - try { - _locks.wait(1000); - } catch (InterruptedException ie) { - } - } - } - } - - public static void unlockIdent(String target) { - synchronized (_locks) { - _locks.remove(target); - _locks.notifyAll(); - } - } -} \ No newline at end of file diff --git a/apps/phttprelay/java/src/net/i2p/phttprelay/PHTTPRelayServlet.java b/apps/phttprelay/java/src/net/i2p/phttprelay/PHTTPRelayServlet.java deleted file mode 100644 index 45744a2d2..000000000 --- a/apps/phttprelay/java/src/net/i2p/phttprelay/PHTTPRelayServlet.java +++ /dev/null @@ -1,75 +0,0 @@ -package net.i2p.phttprelay; - -/* - * free (adj.): unencumbered; not under the control of others - * Written by jrandom in 2003 and released into the public domain - * with no warranty of any kind, either expressed or implied. - * It probably won't make your computer catch on fire, or eat - * your children, but it might. Use at your own risk. - * - */ - -import java.io.File; -import java.io.IOException; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; - -import net.i2p.util.Log; - -abstract class PHTTPRelayServlet extends HttpServlet { - private Log _log = new Log(getClass()); - protected String _baseDir; - - /* config params */ - /*public final static String PARAM_BASEDIR = "baseDir";*/ - public final static String ENV_BASEDIR = "phttpRelay.baseDir"; - - /** match the clock fudge factor on the router, rather than importing the entire router cvs module */ - public final static long CLOCK_FUDGE_FACTOR = 1 * 60 * 1000; - - protected String buildURL(HttpServletRequest req, String path) { - StringBuffer buf = new StringBuffer(); - buf.append(req.getScheme()).append("://"); - buf.append(req.getServerName()).append(":").append(req.getServerPort()); - buf.append(req.getContextPath()); - buf.append(path); - log("URL built: " + buf.toString()); - return buf.toString(); - } - - protected File getIdentDir(String target) throws IOException { - if ((_baseDir == null) || (target == null)) throw new IOException("dir not specified to deal with"); - File baseDir = new File(_baseDir); - if (!baseDir.exists()) { - boolean created = baseDir.mkdirs(); - log("Creating PHTTP Relay Base Directory: " + baseDir.getAbsolutePath() + " - ok? " + created); - } - File identDir = new File(baseDir, target); - log("Ident dir: " + identDir.getAbsolutePath()); - return identDir; - } - - public void init(ServletConfig config) throws ServletException { - super.init(config); - String dir = System.getProperty(ENV_BASEDIR); - if (dir == null) { - _log.warn("Base directory for the polling http relay system not in the environment [" + ENV_BASEDIR + "]"); - _log.warn("Setting the base directory to ./relayDir for " + getServletName()); - _baseDir = ".relayDir"; - } else { - _baseDir = dir; - log("Loaded up " + getServletName() + " with base directory " + _baseDir); - } - } - - public void log(String msg) { - _log.debug(msg); - } - - public void log(String msg, Throwable t) { - _log.debug(msg, t); - } -} \ No newline at end of file diff --git a/apps/phttprelay/java/src/net/i2p/phttprelay/PollServlet.java b/apps/phttprelay/java/src/net/i2p/phttprelay/PollServlet.java deleted file mode 100644 index d1cf4acaf..000000000 --- a/apps/phttprelay/java/src/net/i2p/phttprelay/PollServlet.java +++ /dev/null @@ -1,263 +0,0 @@ -package net.i2p.phttprelay; - -/* - * free (adj.): unencumbered; not under the control of others - * Written by jrandom in 2003 and released into the public domain - * with no warranty of any kind, either expressed or implied. - * It probably won't make your computer catch on fire, or eat - * your children, but it might. Use at your own risk. - * - */ - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Date; - -import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import net.i2p.crypto.DSAEngine; -import net.i2p.data.Base64; -import net.i2p.data.DataFormatException; -import net.i2p.data.DataHelper; -import net.i2p.data.RouterIdentity; -import net.i2p.data.Signature; -import net.i2p.util.Clock; - -/** - * Handle poll requests for new messages - checking the poll request for a valid signature, - * sending back all of the messages found, and after all messages are written out, delete - * them from the local store. If the signature fails, it sends back an HTTP 403 (UNAUTHORIZED). - * If the target is not registered, it sends back an HTTP 404 (NOT FOUND)

- * - * This servlet should be set up in web.xml as follows: - * - * - * Poll - * net.i2p.phttprelay.PollServlet - * - * baseDir - * /usr/local/jetty/phttprelayDir - * - * - * - * - * Poll - * /phttpPoll - * - * - * baseDir is the directory under which registrants and their pending messages are stored - * - */ -public class PollServlet extends PHTTPRelayServlet { - /* URL parameters on the check */ - - /** H(routerIdent).toBase64() of the target to receive the message */ - public final static String PARAM_SEND_TARGET = "target"; - - /** HTTP error code if the target is not known*/ - public final static int CODE_UNKNOWN = HttpServletResponse.SC_NOT_FOUND; - /** HTTP error code if the signature failed */ - public final static int CODE_UNAUTHORIZED = HttpServletResponse.SC_UNAUTHORIZED; - /** HTTP error code if everything is ok */ - public final static int CODE_OK = HttpServletResponse.SC_OK; - - public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - byte data[] = getData(req); - if (data == null) return; - ByteArrayInputStream bais = new ByteArrayInputStream(data); - String target = getTarget(bais); - if (target == null) { - log("Target not specified"); - resp.sendError(CODE_UNKNOWN); - return; - } - - if (!isKnown(target)) { - resp.sendError(CODE_UNKNOWN); - return; - } - - if (!isAuthorized(target, bais)) { - resp.sendError(CODE_UNAUTHORIZED); - return; - } else { - log("Authorized access for target " + target); - } - - sendMessages(resp, target); - } - - private byte[] getData(HttpServletRequest req) throws ServletException, IOException { - ServletInputStream in = req.getInputStream(); - int len = req.getContentLength(); - byte data[] = new byte[len]; - int cur = 0; - int read = DataHelper.read(in, data); - if (read != len) { - log("Size read is incorrect [" + read + " instead of expected " + len + "]"); - return null; - } else { - log("Read data length: " + data.length + " in base64: " + Base64.encode(data)); - return data; - } - } - - private String getTarget(InputStream in) throws IOException { - StringBuffer buf = new StringBuffer(64); - int numBytes = 0; - int c = 0; - while ((c = in.read()) != -1) { - if (c == (int) '&') break; - buf.append((char) c); - numBytes++; - if (numBytes > 128) { - log("Target didn't find the & after 128 bytes [" + buf.toString() + "]"); - return null; - } - } - if (buf.toString().indexOf("target=") != 0) { - log("Did not start with target= [" + buf.toString() + "]"); - return null; - } - return buf.substring("target=".length()); - } - - private void sendMessages(HttpServletResponse resp, String target) throws IOException { - log("Before lock " + target); - LockManager.lockIdent(target); - log("Locked " + target); - try { - File identDir = getIdentDir(target); - expire(identDir); - File messageFiles[] = identDir.listFiles(); - resp.setStatus(CODE_OK); - log("Sending back " + (messageFiles.length - 1) + " messages"); - ServletOutputStream out = resp.getOutputStream(); - DataHelper.writeDate(out, new Date(Clock.getInstance().now())); - DataHelper.writeLong(out, 2, messageFiles.length - 1); - for (int i = 0; i < messageFiles.length; i++) { - if ("identity.dat".equals(messageFiles[i].getName())) { - // skip - } else { - log("Message file " + messageFiles[i].getName() + " is " + messageFiles[i].length() + " bytes"); - DataHelper.writeLong(out, 4, messageFiles[i].length()); - writeFile(out, messageFiles[i]); - boolean deleted = messageFiles[i].delete(); - if (!deleted) { - log("!!!Error removing message file " + messageFiles[i].getAbsolutePath() + " - please delete!"); - } - } - } - out.flush(); - out.close(); - } catch (DataFormatException dfe) { - log("Error sending message", dfe); - } finally { - LockManager.unlockIdent(target); - log("Unlocked " + target); - } - } - - private final static long EXPIRE_DELAY = 60 * 1000; // expire messages every minute - - private void expire(File identDir) throws IOException { - File files[] = identDir.listFiles(); - long now = System.currentTimeMillis(); - for (int i = 0; i < files.length; i++) { - if ("identity.dat".equals(files[i].getName())) { - continue; - } - if (files[i].lastModified() + EXPIRE_DELAY < now) { - log("Expiring " + files[i].getAbsolutePath()); - files[i].delete(); - } - } - } - - private void writeFile(ServletOutputStream out, File file) throws IOException { - FileInputStream fis = new FileInputStream(file); - try { - byte buf[] = new byte[4096]; - while (true) { - int read = DataHelper.read(fis, buf); - if (read > 0) - out.write(buf, 0, read); - else - break; - } - } finally { - fis.close(); - } - } - - private boolean isKnown(String target) throws IOException { - File identDir = getIdentDir(target); - if (identDir.exists()) { - File identFile = new File(identDir, "identity.dat"); - if (identFile.exists()) { - // known and valid (maybe we need to check the file format... naw, fuck it - return true; - } else { - return false; - } - } else { - return false; - } - } - - private boolean isAuthorized(String target, InputStream in) throws IOException { - RouterIdentity ident = null; - try { - ident = getRouterIdentity(target); - } catch (DataFormatException dfe) { - log("Identity was not valid", dfe); - } - - if (ident == null) { - log("Identity not registered"); - return false; - } - - try { - long val = DataHelper.readLong(in, 4); - Signature sig = new Signature(); - sig.readBytes(in); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - DataHelper.writeLong(baos, 4, val); - if (DSAEngine.getInstance().verifySignature(sig, baos.toByteArray(), ident.getSigningPublicKey())) { - return true; - } else { - log("Signature does NOT match"); - return false; - } - } catch (DataFormatException dfe) { - log("Format error reading the nonce and signature", dfe); - return false; - } - } - - private RouterIdentity getRouterIdentity(String target) throws IOException, DataFormatException { - File identDir = getIdentDir(target); - if (identDir.exists()) { - File identFile = new File(identDir, "identity.dat"); - if (identFile.exists()) { - // known and valid (maybe we need to check the file format... naw, fuck it - RouterIdentity ident = new RouterIdentity(); - ident.readBytes(new FileInputStream(identFile)); - return ident; - } else { - return null; - } - } else { - return null; - } - } -} \ No newline at end of file diff --git a/apps/phttprelay/java/src/net/i2p/phttprelay/RegisterServlet.java b/apps/phttprelay/java/src/net/i2p/phttprelay/RegisterServlet.java deleted file mode 100644 index 822228b18..000000000 --- a/apps/phttprelay/java/src/net/i2p/phttprelay/RegisterServlet.java +++ /dev/null @@ -1,158 +0,0 @@ -package net.i2p.phttprelay; - -/* - * free (adj.): unencumbered; not under the control of others - * Written by jrandom in 2003 and released into the public domain - * with no warranty of any kind, either expressed or implied. - * It probably won't make your computer catch on fire, or eat - * your children, but it might. Use at your own risk. - * - */ - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Date; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import net.i2p.data.DataFormatException; -import net.i2p.data.DataHelper; -import net.i2p.data.RouterIdentity; -import net.i2p.util.Clock; - -/** - * Accept registrations for PHTTP relaying, allowing the Polling HTTP (PHTTP) - * transport for I2P to bridge past firewalls, NATs, and proxy servers.

- * - * This servlet should be set up in web.xml as follows: - * - * - * Register - * net.i2p.phttprelay.RegisterServlet - * - * baseDir - * /usr/local/jetty/phttprelayDir - * - * - * pollPath - * phttpPoll - * - * - * sendPath - * phttpSend - * - * - * - * - * Register - * /phttpRegister - * - * - * baseDir is the directory under which registrants and their pending messages are stored - * pollPath is the path under the current host that requests polling for messages should be sent - * sendPath is the path under the current host that requests submitting messages should be sent - * - * The pollPath and sendPath must not start with / as they are translated ala http://host:port/[path] - */ -public class RegisterServlet extends PHTTPRelayServlet { - private String _pollPath; - private String _sendPath; - - /* config params */ - public final static String PARAM_POLL_PATH = "pollPath"; - public final static String PARAM_SEND_PATH = "sendPath"; - - /* key=val keys sent back on registration */ - public final static String PROP_STATUS = "status"; - public final static String PROP_POLL_URL = "pollURL"; - public final static String PROP_SEND_URL = "sendURL"; - public final static String PROP_TIME_OFFSET = "timeOffset"; // ms (local-remote) - - /* values for the PROP_STATUS */ - public final static String STATUS_FAILED = "failed"; - public final static String STATUS_REGISTERED = "registered"; - - public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - ServletInputStream in = req.getInputStream(); - RouterIdentity ident = new RouterIdentity(); - try { - Date remoteTime = DataHelper.readDate(in); - long skew = getSkew(remoteTime); - ident.readBytes(in); - boolean ok = registerIdent(ident); - sendURLs(req, resp, skew, ok); - } catch (DataFormatException dfe) { - log("Invalid format for router identity posted", dfe); - } finally { - in.close(); - } - } - - private long getSkew(Date remoteDate) { - if (remoteDate == null) { - log("*ERROR: remote date was null"); - return Long.MAX_VALUE; - } else { - long diff = Clock.getInstance().now() - remoteDate.getTime(); - return diff; - } - } - - private boolean registerIdent(RouterIdentity ident) throws DataFormatException, IOException { - File identDir = getIdentDir(ident.getHash().toBase64()); - boolean created = identDir.mkdirs(); - File identFile = new File(identDir, "identity.dat"); - FileOutputStream fos = null; - try { - fos = new FileOutputStream(identFile); - ident.writeBytes(fos); - } finally { - if (fos != null) try { - fos.close(); - } catch (IOException ioe) { - } - } - log("Identity registered into " + identFile.getAbsolutePath()); - return true; - } - - private void sendURLs(HttpServletRequest req, HttpServletResponse resp, long skew, boolean ok) throws IOException { - ServletOutputStream out = resp.getOutputStream(); - - log("*Debug: clock skew of " + skew + "ms (local-remote)"); - - StringBuffer buf = new StringBuffer(); - if (ok) { - buf.append(PROP_POLL_URL).append("=").append(buildURL(req, _pollPath)).append("\n"); - buf.append(PROP_SEND_URL).append("=").append(buildURL(req, _sendPath)).append("\n"); - buf.append(PROP_TIME_OFFSET).append("=").append(skew).append("\n"); - buf.append(PROP_STATUS).append("=").append(STATUS_REGISTERED).append("\n"); - } else { - buf.append(PROP_TIME_OFFSET).append("=").append(skew).append("\n"); - buf.append(PROP_STATUS).append("=").append(STATUS_FAILED).append("\n"); - } - out.write(buf.toString().getBytes()); - out.close(); - } - - public void init(ServletConfig config) throws ServletException { - super.init(config); - - String pollPath = config.getInitParameter(PARAM_POLL_PATH); - if (pollPath == null) - throw new ServletException("Polling path for the registration servlet required [" + PARAM_POLL_PATH + "]"); - else - _pollPath = pollPath; - String sendPath = config.getInitParameter(PARAM_SEND_PATH); - if (sendPath == null) - throw new ServletException("Sending path for the registration servlet required [" + PARAM_SEND_PATH + "]"); - else - _sendPath = sendPath; - } -} \ No newline at end of file diff --git a/apps/phttprelay/java/src/net/i2p/phttprelay/SendServlet.java b/apps/phttprelay/java/src/net/i2p/phttprelay/SendServlet.java deleted file mode 100644 index a09a4258c..000000000 --- a/apps/phttprelay/java/src/net/i2p/phttprelay/SendServlet.java +++ /dev/null @@ -1,324 +0,0 @@ -package net.i2p.phttprelay; - -/* - * free (adj.): unencumbered; not under the control of others - * Written by jrandom in 2003 and released into the public domain - * with no warranty of any kind, either expressed or implied. - * It probably won't make your computer catch on fire, or eat - * your children, but it might. Use at your own risk. - * - */ - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * Accept messages for PHTTP relaying, allowing the Polling HTTP (PHTTP) - * transport for I2P to bridge past firewalls, NATs, and proxy servers. This - * delivers them into the queue, returning HTTP 201 (created) if the queue is - * known, as well as the URL at which requests can be made to check the delivery - * status of the message. If the queue is not known, HTTP 410 (resource gone) is - * sent back.

- * - * This servlet should be set up in web.xml as follows: - * - * - * Send - * net.i2p.phttprelay.SendServlet - * - * baseDir - * /usr/local/jetty/phttprelayDir - * - * - * checkPath - * phttpCheckStatus - * - * - * maxMessagesPerIdent - * 100 - * - * - * - * - * Send - * /phttpSend - * - * - * baseDir is the directory under which registrants and their pending messages are stored - * checkPath is the path under the current host that requests for the status of delivery should be sent - * maxMessagesPerIdent is the maximum number of outstanding messages per peer being relayed - * - * The checkPath must not start with / as they are translated ala http://host:port/[path] - */ -public class SendServlet extends PHTTPRelayServlet { - private String _checkPath; - private int _maxMessagesPerIdent; - - /* config params */ - public final static String PARAM_CHECK_PATH = "checkPath"; - public final static String PARAM_MAX_MESSAGES_PER_IDENT = "maxMessagesPerIdent"; - - /* URL parameters on the send */ - - /** H(routerIdent).toBase64() of the target to receive the message */ - public final static String PARAM_SEND_TARGET = "target"; - /** # ms to wait for the message to be delivered before failing it */ - public final static String PARAM_SEND_TIMEOUTMS = "timeoutMs"; - /** # bytes to be sent in the message */ - public final static String PARAM_SEND_DATA_LENGTH = "dataLength"; - /** sending router's time in ms */ - public final static String PARAM_SEND_TIME = "localTime"; - - /** msgId parameter to access the check path servlet with (along side PARAM_SEND_TARGET) */ - public final static String PARAM_MSG_ID = "msgId"; - - /* key=val keys sent back on registration */ - public final static String PROP_CHECK_URL = "statusCheckURL"; - public final static String PROP_STATUS = "status"; - public final static String STATUS_OK = "accepted"; - public final static String STATUS_UNKNOWN = "unknown"; - private final static String STATUS_CLOCKSKEW = "clockSkew_"; - - /** prefix for (local-remote) */ - - public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - ServletInputStream in = req.getInputStream(); - try { - int contentLen = req.getContentLength(); - String firstLine = getFirstLine(in, contentLen); - if (firstLine == null) { return; } - Map params = getParameters(firstLine); - String target = (String) params.get(PARAM_SEND_TARGET); - String timeoutStr = (String) params.get(PARAM_SEND_TIMEOUTMS); - String lenStr = (String) params.get(PARAM_SEND_DATA_LENGTH); - String remoteTimeStr = (String) params.get(PARAM_SEND_TIME); - long skew = 0; - try { - long remTime = Long.parseLong(remoteTimeStr); - skew = System.currentTimeMillis() - remTime; - } catch (Throwable t) { - skew = Long.MAX_VALUE; - log("*ERROR could not parse the remote time from [" + remoteTimeStr + "]"); - } - - log("Target [" + target + "] timeout [" + timeoutStr + "] length [" + lenStr + "] skew [" + skew + "]"); - - if ((skew > CLOCK_FUDGE_FACTOR) || (skew < 0 - CLOCK_FUDGE_FACTOR)) { - log("Attempt to send by a skewed router: skew = " + skew + "ms (local-remote)"); - failSkewed(req, resp, skew); - } - - if (!isValidTarget(target)) { - log("Attempt to send to an invalid target [" + target + "]"); - fail(req, resp, "Unknown or invalid target"); - return; - } - - long len = -1; - try { - len = Long.parseLong(lenStr); - } catch (Throwable t) { - log("Unable to parse length parameter [" + PARAM_SEND_DATA_LENGTH + "] (" + lenStr + ")"); - fail(req, resp, "Invalid length parameter"); - return; - } - - int msgId = saveFile(in, resp, target, len); - if (msgId >= 0) { - sendSuccess(req, resp, target, msgId); - } else { - fail(req, resp, "Unable to queue up the message for delivery"); - } - } finally { - try { - in.close(); - } catch (IOException ioe) { - } - } - } - - private String getFirstLine(ServletInputStream in, int len) throws ServletException, IOException { - StringBuffer buf = new StringBuffer(128); - int numBytes = 0; - int c = 0; - while ((c = in.read()) != -1) { - if (c == (int) '\n') break; - buf.append((char) c); - numBytes++; - if (numBytes > 512) { - log("First line is > 512 bytes [" + buf.toString() + "]"); - return null; - } - } - log("First line: " + buf.toString()); - return buf.toString(); - } - - private static Map getParameters(String line) { - //StringTokenizer tok = new StringTokenizer(line, "&=", true); - Map params = new HashMap(); - while (line != null) { - String key = null; - String val = null; - int firstAmp = line.indexOf('&'); - int firstEq = line.indexOf('='); - if (firstAmp > 0) { - key = line.substring(0, firstEq); - val = line.substring(firstEq + 1, firstAmp); - line = line.substring(firstAmp + 1); - params.put(key, val); - } else { - line = null; - } - } - return params; - } - - private boolean isValidTarget(String target) throws IOException { - File identDir = getIdentDir(target); - if (identDir.exists()) { - File identFile = new File(identDir, "identity.dat"); - if (identFile.exists()) { - // known and valid (maybe we need to check the file format... naw, fuck it - String files[] = identDir.list(); - // we skip 1 because of identity.dat - if (files.length - 1 > _maxMessagesPerIdent) { - log("Too many messages pending for " + target + ": " + (files.length - 1)); - return false; - } else { - return true; - } - } else { - log("Ident directory exists, but identity does not... corrupt for " + target); - return false; - } - } else { - log("Unknown ident " + target); - return false; - } - } - - private int saveFile(InputStream in, HttpServletResponse resp, String target, long len) throws IOException { - File identDir = getIdentDir(target); - if (!identDir.exists()) return -1; - try { - LockManager.lockIdent(target); - int i = 0; - while (true) { - File curFile = new File(identDir, "msg" + i + ".dat"); - if (!curFile.exists()) { - boolean ok = writeFile(curFile, in, len); - if (ok) - return i; - else - return -1; - } - i++; - continue; - } - } finally { - LockManager.unlockIdent(target); - } - } - - private boolean writeFile(File file, InputStream in, long len) throws IOException { - long remaining = len; - FileOutputStream fos = null; - try { - fos = new FileOutputStream(file); - byte buf[] = new byte[4096]; - while (remaining > 0) { - int read = in.read(buf); - if (read == -1) break; - remaining -= read; - if (read > 0) fos.write(buf, 0, read); - } - } finally { - if (fos != null) { - try { - fos.close(); - } catch (IOException ioe) { - } - } - if (remaining != 0) { - log("Invalid remaining bytes [" + remaining + " out of " + len - + "] - perhaps message was cancelled partway through delivery? deleting " + file.getAbsolutePath()); - boolean deleted = file.delete(); - if (!deleted) log("!!!Error deleting temporary file " + file.getAbsolutePath()); - return false; - } - } - return true; - } - - private void sendSuccess(HttpServletRequest req, HttpServletResponse resp, String target, int msgId) - throws IOException { - ServletOutputStream out = resp.getOutputStream(); - StringBuffer buf = new StringBuffer(); - buf.append(PROP_STATUS).append('=').append(STATUS_OK).append('\n'); - buf.append(PROP_CHECK_URL).append('=').append(buildURL(req, _checkPath)); - buf.append('?'); - buf.append(PARAM_SEND_TARGET).append('=').append(target).append("&"); - buf.append(PARAM_MSG_ID).append('=').append(msgId).append("\n"); - out.write(buf.toString().getBytes()); - out.flush(); - } - - private void fail(HttpServletRequest req, HttpServletResponse resp, String err) throws IOException { - ServletOutputStream out = resp.getOutputStream(); - StringBuffer buf = new StringBuffer(); - buf.append(PROP_STATUS).append('=').append(STATUS_UNKNOWN).append('\n'); - out.write(buf.toString().getBytes()); - out.flush(); - } - - private void failSkewed(HttpServletRequest req, HttpServletResponse resp, long skew) throws IOException { - ServletOutputStream out = resp.getOutputStream(); - StringBuffer buf = new StringBuffer(); - buf.append(PROP_STATUS).append('=').append(STATUS_CLOCKSKEW).append(skew).append('\n'); - out.write(buf.toString().getBytes()); - out.flush(); - } - - public void init(ServletConfig config) throws ServletException { - super.init(config); - - String checkPath = config.getInitParameter(PARAM_CHECK_PATH); - if (checkPath == null) - throw new ServletException("Check status path for the sending servlet required [" + PARAM_CHECK_PATH + "]"); - else - _checkPath = checkPath; - - String maxMessagesPerIdentStr = config.getInitParameter(PARAM_MAX_MESSAGES_PER_IDENT); - if (maxMessagesPerIdentStr == null) - throw new ServletException("Max messages per ident for the sending servlet required [" - + PARAM_MAX_MESSAGES_PER_IDENT + "]"); - try { - _maxMessagesPerIdent = Integer.parseInt(maxMessagesPerIdentStr); - } catch (Throwable t) { - throw new ServletException("Valid max messages per ident for the sending servlet required [" - + PARAM_MAX_MESSAGES_PER_IDENT + "]"); - } - } - - public static void main(String args[]) { - String line = "target=pp0ARjQiB~IKC-0FsMUsPEMrwR3gxVBZGRYfEr1IzHI=&timeoutMs=52068&dataLength=2691&"; - Map props = getParameters(line); - for (java.util.Iterator iter = props.keySet().iterator(); iter.hasNext();) { - String key = (String) iter.next(); - String val = (String) props.get(key); - System.out.println("[" + key + "] = [" + val + "]"); - } - } -} \ No newline at end of file diff --git a/apps/phttprelay/java/web.xml b/apps/phttprelay/java/web.xml deleted file mode 100644 index 8a82891fe..000000000 --- a/apps/phttprelay/java/web.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - I2P Polling HTTP Relay - - - Register - net.i2p.phttprelay.RegisterServlet - - pollPath - /phttpPoll - - - sendPath - /phttpSend - - 1 - - - - Send - net.i2p.phttprelay.SendServlet - - checkPath - /phttpCheckSendStatus - - - maxMessagesPerIdent - 100 - - 1 - - - - CheckSendStatus - net.i2p.phttprelay.CheckSendStatusServlet - 1 - - - - Poll - net.i2p.phttprelay.PollServlet - 1 - - - - Register - /phttpRegister - - - - Send - /phttpSend - - - - CheckSendStatus - /phttpCheckSendStatus - - - - Poll - /phttpPoll - - - diff --git a/apps/tests/COPYING b/apps/tests/COPYING deleted file mode 100644 index 5ec43ee15..000000000 --- a/apps/tests/COPYING +++ /dev/null @@ -1,278 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. diff --git a/apps/tests/EchoServer.java b/apps/tests/EchoServer.java deleted file mode 100644 index 1ffe8f2e3..000000000 --- a/apps/tests/EchoServer.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * A Minimal echo server. - * - * Copyright (c) 2004 Michael Schierl - * - * Licensed unter GNU General Public License. - */ - -import java.io.*; -import java.net.*; - -public class EchoServer extends Thread { - - public static void main(String[] args) throws IOException { - ServerSocket ss = new ServerSocket(Integer.parseInt(args[0])); - while (true) { - Socket s = ss.accept(); - new EchoServer(s); - } - } - - private Socket s; - - public EchoServer(Socket s) { - this.s=s; - start(); - } - - public void run() { - try { - InputStream in = s.getInputStream(); - OutputStream out = s.getOutputStream(); - byte[] b = new byte[4096]; - int len; - while ((len = in.read(b)) != -1) { - out.write(b, 0, len); - } - } catch (SocketException ex) { - // nothing - } catch (IOException ex) { - ex.printStackTrace(); - } - } -} diff --git a/apps/tests/GuaranteedBug.java b/apps/tests/GuaranteedBug.java deleted file mode 100644 index 147b84526..000000000 --- a/apps/tests/GuaranteedBug.java +++ /dev/null @@ -1,106 +0,0 @@ -// compile & run this file against i2p.jar - -import java.io.*; -import java.util.*; -import net.i2p.*; -import net.i2p.client.*; -import net.i2p.data.*; - -public class GuaranteedBug { - - - public void reproduce() { - try { - Destination d1 = null; - // first client (receiver) - if (true) { // smaller scope for variables ... - I2PClient client = I2PClientFactory.createClient(); - ByteArrayOutputStream keyStream = - new ByteArrayOutputStream(512); - d1 = client.createDestination(keyStream); - ByteArrayInputStream in = - new ByteArrayInputStream(keyStream.toByteArray()); - Properties opts = new Properties(); - opts.setProperty(I2PClient.PROP_RELIABILITY, - I2PClient.PROP_RELIABILITY_GUARANTEED); - opts.setProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1"); - opts.setProperty(I2PClient.PROP_TCP_PORT, "7654"); - I2PSession session = client.createSession(in, opts); - session.connect(); - session.setSessionListener(new PacketCounter()); - } - // second client (sender) - I2PClient client = I2PClientFactory.createClient(); - ByteArrayOutputStream keyStream = new ByteArrayOutputStream(512); - Destination d2 = client.createDestination(keyStream); - ByteArrayInputStream in = - new ByteArrayInputStream(keyStream.toByteArray()); - Properties opts = new Properties(); - opts.setProperty(I2PClient.PROP_RELIABILITY, - I2PClient.PROP_RELIABILITY_GUARANTEED); - opts.setProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1"); - opts.setProperty(I2PClient.PROP_TCP_PORT, "7654"); - I2PSession session = client.createSession(in, opts); - session.connect(); - session.setSessionListener(new DummyListener()); - for (int i=0;i<1000; i++) { - byte[] msg = (""+i).getBytes("ISO-8859-1"); - session.sendMessage(d1,msg); - System.out.println(">>"+i); - } - } catch (IOException ex) { - ex.printStackTrace(); - } catch (I2PException ex) { - ex.printStackTrace(); - } - } - - public static void main(String[] args) { - new GuaranteedBug().reproduce(); - } - - // ------------------------------------------------------- - public class DummyListener implements I2PSessionListener { - public void disconnected(I2PSession session) { - System.err.println("Disconnected: "+session); - } - - public void errorOccurred(I2PSession session, String message, - Throwable error) { - System.err.println("Error: "+session+"/"+message); - error.printStackTrace(); - } - - public void messageAvailable(I2PSession session, int msgId, - long size) { - System.err.println("Message here? "+session); - } - - public void reportAbuse(I2PSession session, int severity) { - System.err.println("Abuse: "+severity+"/"+session); - } - } - - public class PacketCounter extends DummyListener { - private int lastPacket = -1; - public void messageAvailable(I2PSession session, int msgId, - long size) { - try { - byte msg[] = session.receiveMessage(msgId); - String m = new String(msg, "ISO-8859-1"); - int no = Integer.parseInt(m); - if (no != ++lastPacket) { - System.out.println("ERROR: <<"+no); - } else { - System.out.println("<<"+no); - } - } catch (NumberFormatException ex) { - ex.printStackTrace(); - } catch (I2PException ex) { - ex.printStackTrace(); - } catch (IOException ex) { - ex.printStackTrace(); - } - } - } -} diff --git a/apps/tests/README b/apps/tests/README deleted file mode 100644 index 83f17a4a8..000000000 --- a/apps/tests/README +++ /dev/null @@ -1,6 +0,0 @@ -This directory is intended for tests which are useful for testing -I2P, but don't test any of the I2P components directly. Instead, -tests are run on "application" level (TCP, IRC, HTTP etc.). - -IOW: These tests may be useful for any other project that allows -tunneling of "normal" protocols, not only I2P. diff --git a/apps/tests/echotester/BasicEchoTestAnalyzer.java b/apps/tests/echotester/BasicEchoTestAnalyzer.java deleted file mode 100644 index 577db8feb..000000000 --- a/apps/tests/echotester/BasicEchoTestAnalyzer.java +++ /dev/null @@ -1,88 +0,0 @@ -/** - * A basic implementation for the EchoTestAnalyzer. - */ -public class BasicEchoTestAnalyzer implements EchoTestAnalyzer { - - /** - * How many events must appear until a detailed report is - * printed. Default is every 20 events. - */ - private static int REPORT_DELAY = 20; - - private static int SUMMARY_SIZE = 100; - - public BasicEchoTestAnalyzer() { - this(20, 100); - } - - public BasicEchoTestAnalyzer(int reportDelay, int summarySize) { - REPORT_DELAY = reportDelay; - SUMMARY_SIZE = summarySize; - } - - private int events = 0, packetLosses = 0, packetLossesDisconnect = 0, disconnects = 0, disconnectsRefused = 0, - delayCount = 0, lastDelayPtr = 0; - private long minDelay = Long.MAX_VALUE, maxDelay = 0, delaySum = 0; - private long[] lastDelays = new long[SUMMARY_SIZE]; - - public synchronized void packetLossOccurred(boolean beforeDisconnect) { - System.out.println("1: Packet lost" + (beforeDisconnect ? " before disconnect" : "") + "."); - packetLosses++; - if (beforeDisconnect) packetLossesDisconnect++; - countEvent(); - } - - public synchronized void successOccurred(long delay) { - System.out.println("0: Delay = " + delay); - if (delay > maxDelay) maxDelay = delay; - if (delay < minDelay) minDelay = delay; - delaySum += delay; - delayCount++; - lastDelays[lastDelayPtr++] = delay; - lastDelayPtr %= SUMMARY_SIZE; - countEvent(); - } - - public synchronized void disconnected(boolean refused) { - System.out.println("2: Disconnected" + (refused ? " (connection refused)" : "") + "."); - disconnects++; - if (refused) disconnectsRefused++; - countEvent(); - } - - private void countEvent() { - events++; - if (events % REPORT_DELAY == 0) { - int packets = packetLosses + delayCount; - long delaySummary = 0; - for (int i = 0; i < SUMMARY_SIZE; i++) { - delaySummary += lastDelays[i]; - } - System.out.println("++++++++++++++++ ECHO STATISTICS +++++++++++++++++++++++++" - + "\n++ Number of total echo messages: " - + packets - + "\n++ No response for " - + packetLosses - + "\n++ (of which " - + packetLossesDisconnect - + " due to a disconnect)" - + "\n++ Disconnects: " - + disconnects - + "\n++ (of which " - + disconnectsRefused - + " due to 'connection refused')" - + (disconnects > 0 || true ? "\n++ Average lost packets per disconnect: " - + (packetLossesDisconnect / (float) disconnects) : "") - + "\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - + "\n++ Minimal delay: " - + minDelay - + "\n++ Average delay: " - + (delaySum / (float) delayCount) - + "\n++ Maximal delay: " - + maxDelay - + (delayCount >= SUMMARY_SIZE ? "\n++ Average delay over last " + SUMMARY_SIZE + ": " - + (delaySummary / (float) SUMMARY_SIZE) : "") - + "\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); - } - } -} \ No newline at end of file diff --git a/apps/tests/echotester/EchoTestAnalyzer.java b/apps/tests/echotester/EchoTestAnalyzer.java deleted file mode 100644 index 96c5f715b..000000000 --- a/apps/tests/echotester/EchoTestAnalyzer.java +++ /dev/null @@ -1,17 +0,0 @@ - -/** - * A class that wants to analyze tests implements this interface. This - * allows to "mix" several test values (from different echo servers) - * as well as different algorithms for analyzing the data (for - * jrandom: Strategy Pattern *g*). - */ -public interface EchoTestAnalyzer { - - public void packetLossOccurred(boolean beforeDisconnect); - - public void successOccurred(long delay); - - public void disconnected(boolean refused); - -} - diff --git a/apps/tests/echotester/EchoTester.java b/apps/tests/echotester/EchoTester.java deleted file mode 100644 index 750ccb7ba..000000000 --- a/apps/tests/echotester/EchoTester.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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; - } - } - } -} \ No newline at end of file diff --git a/apps/tests/readme.license.txt b/apps/tests/readme.license.txt deleted file mode 100644 index 4c14112cb..000000000 --- a/apps/tests/readme.license.txt +++ /dev/null @@ -1,10 +0,0 @@ -$Id$ - -the i2p/apps/tests module is the root of application -level tests, and everything within it is released -according to the terms of the I2P license policy. -That means everything contained within the -i2p/apps/tests module is released into the public -domain unless otherwise marked. Alternate licenses -that may be used include GPL, GPL + java exception, -BSD, Cryptix, and MIT.