diff --git a/apps/BOB/src/net/i2p/BOB/DoCMDS.java b/apps/BOB/src/net/i2p/BOB/DoCMDS.java index 16da28ce9c019e2b588cacf7d83d0983e260e6e0..1a2d2a19a6f0c7552e4798c3bbcfd701b4f657c3 100644 --- a/apps/BOB/src/net/i2p/BOB/DoCMDS.java +++ b/apps/BOB/src/net/i2p/BOB/DoCMDS.java @@ -1263,11 +1263,11 @@ public class DoCMDS implements Runnable { tunnel = new MUXlisten(database, nickinfo, _log); Thread t = new Thread(tunnel); t.start(); - try { - Thread.sleep(1000 * 10); // Slow down the startup. - } catch(InterruptedException ie) { - // ignore it - } + // try { + // Thread.sleep(1000 * 10); // Slow down the startup. + // } catch(InterruptedException ie) { + // // ignore it + // } out.println("OK tunnel starting"); } catch (I2PException e) { out.println("ERROR starting tunnel: " + e); diff --git a/apps/BOB/src/net/i2p/BOB/I2Plistener.java b/apps/BOB/src/net/i2p/BOB/I2Plistener.java index a8115893db8ca2f650bf976407356e647ecb0354..3bb94e0b37582344111d946e4b9ceaf38b4d0281 100644 --- a/apps/BOB/src/net/i2p/BOB/I2Plistener.java +++ b/apps/BOB/src/net/i2p/BOB/I2Plistener.java @@ -82,18 +82,6 @@ public class I2Plistener implements Runnable { die: { serverSocket.setSoTimeout(50); -// try { -// if (info.exists("INPORT")) { -// tgwatch = 2; -// } -// } catch (Exception e) { -// try { -// runlock(); -// } catch (Exception e2) { -// break die; -// } -// break die; -// } boolean spin = true; while (spin) { @@ -129,40 +117,12 @@ die: { t.start(); } - } catch (I2PException e) { + } catch (Exception e) { // System.out.println("Exception " + e); } } } // System.out.println("I2Plistener: Close"); - - - // Previous level does this cleanup now. - // - // try { - // serverSocket.close(); - // } catch (I2PException e) { - // nop - //} - // need to kill off the socket manager too. - // I2PSession session = socketManager.getSession(); - // if (session != null) { - // System.out.println("I2Plistener: destroySession"); - // try { - // session.destroySession(); - // } catch (I2PSessionException ex) { - // nop - // } - //} - // System.out.println("I2Plistener: Waiting for children"); - // while (Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish - // try { - // Thread.sleep(100); //sleep for 100 ms (One tenth second) - // } catch (Exception e) { - // nop - // } - //} - // System.out.println("I2Plistener: Done."); } } diff --git a/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java b/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java index 0984823b6e631ee19f8ff5a73e185fa3cdae808d..ad5e2701b494bbe9486bbc6b1b6731903a1110a7 100644 --- a/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java +++ b/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java @@ -23,7 +23,6 @@ */ package net.i2p.BOB; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; diff --git a/apps/BOB/src/net/i2p/BOB/MUXlisten.java b/apps/BOB/src/net/i2p/BOB/MUXlisten.java index dc30c5445d0d31ca3e668e5b1cf14a491f21b112..2c7a64924725f590defeb6768ac0a77db6902458 100644 --- a/apps/BOB/src/net/i2p/BOB/MUXlisten.java +++ b/apps/BOB/src/net/i2p/BOB/MUXlisten.java @@ -133,7 +133,7 @@ public class MUXlisten implements Runnable { */ public void run() { I2PServerSocket SS = null; - int ticks = 1200; // Allow 120 seconds, no more. + int ticks = 100; // Allow 10 seconds, no more. try { wlock(); try { @@ -152,11 +152,11 @@ public class MUXlisten implements Runnable { } // socketManager.addDisconnectListener(new DisconnectListener()); -quit: + quit: { try { tg = new ThreadGroup(N); -die: + die: { // toss the connections to a new threads. // will wrap with TCP and UDP when UDP works @@ -255,7 +255,7 @@ die: try { session.destroySession(); } catch (I2PSessionException ex) { - // nop + // nop } } try { @@ -266,8 +266,8 @@ die: // Wait for child threads and thread groups to die // System.out.println("MUXlisten: waiting for children"); if (tg.activeCount() + tg.activeGroupCount() != 0) { + tg.interrupt(); // give my stuff a small smack. while ((tg.activeCount() + tg.activeGroupCount() != 0) && ticks != 0) { - tg.interrupt(); // unwedge any blocking threads. ticks--; try { Thread.sleep(100); //sleep for 100 ms (One tenth second) @@ -288,8 +288,24 @@ die: } } // quit - // This is here to catch when something fucks up REALLY bad. + // zero out everything. + try { + wlock(); + try { + info.add("STARTING", new Boolean(false)); + info.add("STOPPING", new Boolean(false)); + info.add("RUNNING", new Boolean(false)); + } catch (Exception e) { + wunlock(); + return; + } + wunlock(); + } catch (Exception e) { + } + + // This is here to catch when something fucks up REALLY bad, like those annoying stuck threads! if (tg != null) { + tg.interrupt(); // give my stuff a small smack again. if (SS != null) { try { SS.close(); @@ -303,63 +319,85 @@ die: } catch (IOException e) { } } + I2PSession session = socketManager.getSession(); + if (session != null) { + // System.out.println("I2Plistener: destroySession"); + try { + session.destroySession(); + } catch (I2PSessionException ex) { + // nop + } + } try { socketManager.destroySocketManager(); } catch (Exception e) { // nop } - ticks = 600; // 60 seconds + // ticks = 100; // 10 seconds if (tg.activeCount() + tg.activeGroupCount() != 0) { - while ((tg.activeCount() + tg.activeGroupCount() != 0) && ticks != 0) { - tg.interrupt(); // unwedge any blocking threads. - ticks--; + int foo = tg.activeCount() + tg.activeGroupCount(); + int bar = foo; + String boner = tg.getName(); + System.out.println("BOB: MUXlisten: Waiting on threads for " + boner); + System.out.println("\n\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner); + visit(tg, 0, boner); + System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n\n"); + // Happily spin forever :-( + while ((tg.activeCount() + tg.activeGroupCount() != 0)) { + foo = tg.activeCount() + tg.activeGroupCount(); + if (foo != bar) { + System.out.println("\n\nBOB: MUXlisten: ThreadGroup dump BEGIN " + boner); + visit(tg, 0, boner); + System.out.println("BOB: MUXlisten: ThreadGroup dump END " + boner + "\n\n"); + } + bar = foo; + try { + session = socketManager.getSession(); + if (session != null) { + // System.out.println("I2Plistener: destroySession"); + try { + session.destroySession(); + } catch (I2PSessionException ex) { + // nop + } + } + try { + socketManager.destroySocketManager(); + } catch (Exception e) { + // nop + } + } catch (Exception e) { + // nop + } + // tg.interrupt(); // unwedge any blocking threads. + // ticks--; try { Thread.sleep(100); //sleep for 100 ms (One tenth second) } catch (InterruptedException ex) { // nop } } + System.out.println("BOB: MUXlisten: Threads went away. Success: " + boner); } - if (tg.activeCount() + tg.activeGroupCount() == 0) { - tg.destroy(); - // Zap reference to the ThreadGroup so the JVM can GC it. - tg = null; - } else { - System.out.println("BOB: MUXlisten: Can't kill threads. Please send the following dump to sponge@mail.i2p"); - System.out.println("\n\nBOB: MUXlisten: ThreadGroup dump BEGIN"); - visit(tg, 0); - System.out.println("BOB: MUXlisten: ThreadGroup dump END\n\n"); - } +// if (tg.activeCount() + tg.activeGroupCount() == 0) { + tg.destroy(); + // Zap reference to the ThreadGroup so the JVM can GC it. + tg = null; +// } else { +// System.out.println("BOB: MUXlisten: Forcibly killing threads."); +// System.out.println("\n\nBOB: MUXlisten: ThreadGroup dump BEGIN"); +// visit(tg, 0); +// System.out.println("BOB: MUXlisten: ThreadGroup dump END\n\n"); +// nuke(tg,0); +// tg.destroy(); +// // Zap reference to the ThreadGroup so the JVM can GC it. +// tg = null; +// } } - - // This is here to catch when something fucks up REALLY bad. -// if (tg != null) { -// System.out.println("BOB: MUXlisten: Something fucked up REALLY bad!"); -// System.out.println("BOB: MUXlisten: Please email the following dump to sponge@mail.i2p"); -// WrapperManager.requestThreadDump(); -// System.out.println("BOB: MUXlisten: Something fucked up REALLY bad!"); -// System.out.println("BOB: MUXlisten: Please email the above dump to sponge@mail.i2p"); -// } - // zero out everything. - try { - wlock(); - try { - info.add("STARTING", new Boolean(false)); - info.add("STOPPING", new Boolean(false)); - info.add("RUNNING", new Boolean(false)); - } catch (Exception e) { - wunlock(); - return; - } - wunlock(); - } catch (Exception e) { - } - } // Debugging... - /** * Find the root thread group and print them all. * @@ -371,7 +409,7 @@ die: } // Visit each thread group - visit(root, 0); + visit(root, 0, root.getName()); } /** @@ -379,7 +417,7 @@ die: * @param group ThreadGroup to visit * @param level Current level */ - private static void visit(ThreadGroup group, int level) { + private static void visit(ThreadGroup group, int level, String tn) { // Get threads in `group' int numThreads = group.activeCount(); Thread[] threads = new Thread[numThreads * 2]; @@ -389,7 +427,36 @@ die: for (int i = 0; i < numThreads; i++) { // Get thread Thread thread = threads[i]; - System.out.println("BOB: MUXlisten: " + indent + thread.toString()); + System.out.println("BOB: MUXlisten: " + tn + ": " + indent + thread.toString()); + } + + // Get thread subgroups of `group' + int numGroups = group.activeGroupCount(); + ThreadGroup[] groups = new ThreadGroup[numGroups * 2]; + numGroups = group.enumerate(groups, false); + + // Recursively visit each subgroup + for (int i = 0; i < numGroups; i++) { + visit(groups[i], level + 1, groups[i].getName()); + } + } + + private static void nuke(ThreadGroup group, int level) { + // Get threads in `group' + int numThreads = group.activeCount(); + Thread[] threads = new Thread[numThreads * 2]; + numThreads = group.enumerate(threads, false); + // Enumerate each thread in `group' and stop it. + for (int i = 0; i < numThreads; i++) { + // Get thread + Thread thread = threads[i]; + try { + if (thread.isAlive()) { + thread.stop(); + } + } catch (SecurityException se) { + //nop + } } // Get thread subgroups of `group' @@ -399,7 +466,14 @@ die: // Recursively visit each subgroup for (int i = 0; i < numGroups; i++) { - visit(groups[i], level + 1); + nuke(groups[i], level + 1); + } + try { + group.destroy(); + } catch (IllegalThreadStateException IE) { + //nop + } catch (SecurityException se) { + //nop } } } diff --git a/apps/BOB/src/net/i2p/BOB/TCPio.java b/apps/BOB/src/net/i2p/BOB/TCPio.java index d4b353c5498053592e88e8531c919ae2123d24bd..d92a5cef07f8d0025f184a7f0c9d125e8e56fe80 100644 --- a/apps/BOB/src/net/i2p/BOB/TCPio.java +++ b/apps/BOB/src/net/i2p/BOB/TCPio.java @@ -87,23 +87,13 @@ public class TCPio implements Runnable { boolean spin = true; try { while(spin) { - // database.getReadLock(); - // info.getReadLock(); - // spin = info.get("RUNNING").equals(Boolean.TRUE); - // info.releaseReadLock(); - // database.releaseReadLock(); b = Ain.read(a, 0, 1); - // System.out.println(info.get("NICKNAME").toString() + " " + b); if(b > 0) { Aout.write(a, 0, b); } else if(b == 0) { Thread.yield(); // this should act like a mini sleep. if(Ain.available() == 0) { -// try { - // Thread.yield(); Thread.sleep(10); -// } catch(InterruptedException ex) { -// } } } else { /* according to the specs: @@ -119,19 +109,16 @@ public class TCPio implements Runnable { return; } } - // System.out.println("TCPio: RUNNING = false"); } catch(Exception e) { // Eject!!! Eject!!! //System.out.println("TCPio: Caught an exception " + e); try { Ain.close(); } catch (IOException ex) { -// Logger.getLogger(TCPio.class.getName()).log(Level.SEVERE, null, ex); } try { Aout.close(); } catch (IOException ex) { -// Logger.getLogger(TCPio.class.getName()).log(Level.SEVERE, null, ex); } return; } diff --git a/apps/BOB/src/net/i2p/BOB/TCPlistener.java b/apps/BOB/src/net/i2p/BOB/TCPlistener.java index 78155eb787057f4e00e4e1beeed61fc57b9218e7..4ce888090bc6d0dc84a1815f417a9d060945c323 100644 --- a/apps/BOB/src/net/i2p/BOB/TCPlistener.java +++ b/apps/BOB/src/net/i2p/BOB/TCPlistener.java @@ -73,16 +73,6 @@ public class TCPlistener implements Runnable { info.releaseReadLock(); } - private void wlock() throws Exception { - database.getWriteLock(); - info.getWriteLock(); - } - - private void wunlock() throws Exception { - info.releaseWriteLock(); - database.releaseWriteLock(); - } - /** * Simply listen on TCP port, and thread connections * @@ -116,7 +106,7 @@ die: { } try { Socket server = new Socket(); - listener.setSoTimeout(50); // Half of the expected time from MUXlisten + listener.setSoTimeout(50); // We don't block, we cycle and check. while (spin) { try { rlock(); @@ -141,73 +131,20 @@ die: { } if (g) { // toss the connection to a new thread. - TCPtoI2P conn_c = new TCPtoI2P(socketManager, server /* , info, database */); + TCPtoI2P conn_c = new TCPtoI2P(socketManager, server); Thread t = new Thread(conn_c, "BOBTCPtoI2P"); t.start(); g = false; } } - //System.out.println("TCPlistener: destroySession"); listener.close(); } catch (IOException ioe) { try { listener.close(); } catch (IOException e) { } - // Fatal failure, cause a stop event - try { - rlock(); - try { - spin = info.get("RUNNING").equals(Boolean.TRUE); - } catch (Exception e) { - runlock(); - break die; - } - } catch (Exception e) { - break die; - } - if (spin) { - try { - wlock(); - try { - info.add("STOPPING", new Boolean(true)); - info.add("RUNNING", new Boolean(false)); - } catch (Exception e) { - wunlock(); - break die; - } - } catch (Exception e) { - break die; - } - try { - wunlock(); - } catch (Exception e) { - break die; - } - } } } - // Previous level does this cleanup now. - // - // need to kill off the socket manager too. - // I2PSession session = socketManager.getSession(); - // if (session != null) { - // try { - // session.destroySession(); - // } catch (I2PSessionException ex) { - // nop - // } - //} - //System.out.println("TCPlistener: Waiting for children"); - //while (Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish - // try { - // Thread.sleep(100); //sleep for 100 ms (One tenth second) - // } catch (Exception e) { - // // nop - // } - //} //System.out.println("TCPlistener: Done."); } } - - diff --git a/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java b/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java index c376e16fe1bf8af9dd1e8f5ac25cd5d3a745936c..5fefae017852e2e58e1b98934b48a4845ca316f9 100644 --- a/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java +++ b/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java @@ -151,13 +151,8 @@ public class TCPtoI2P implements Runnable { t.start(); q.start(); while(t.isAlive() && q.isAlive()) { // AND is used here to kill off the other thread -// try { Thread.sleep(10); //sleep for 10 ms -// } catch(InterruptedException e) { - // nop -// } } - // System.out.println("TCPtoI2P: Going away..."); } catch(I2PException e) { Emsg("ERROR " + e.toString(), out); @@ -166,7 +161,7 @@ public class TCPtoI2P implements Runnable { } catch(NoRouteToHostException e) { Emsg("ERROR " + e.toString(), out); } catch(InterruptedIOException e) { - Emsg("ERROR " + e.toString(), out); + // We're breaking away. } } catch(Exception e) { diff --git a/apps/addressbook/build.xml b/apps/addressbook/build.xml index b28cec2dcc4299e5749d0419cba018cf89494fd5..6332c5bcc6d6345d0c42103bf94faf3a949725ee 100644 --- a/apps/addressbook/build.xml +++ b/apps/addressbook/build.xml @@ -6,6 +6,7 @@ <property name="dist" location="dist"/> <property name="jar" value="addressbook.jar"/> <property name="war" value="addressbook.war"/> + <property name="javac.compilerargs" value="" /> <target name="init"> <mkdir dir="${build}"/> @@ -38,6 +39,7 @@ <target name="compile" depends="init, depend"> <javac debug="true" deprecation="on" source="1.5" target="1.5" srcdir="${src}" destdir="${build}"> + <compilerarg line="${javac.compilerargs}" /> <classpath> <pathelement location="../../core/java/build/i2p.jar" /> <pathelement location="../jetty/jettylib/javax.servlet.jar" /> diff --git a/apps/desktopgui/src/router/configuration/PeerHelper.java b/apps/desktopgui/src/router/configuration/PeerHelper.java index f5930970559cbbe4c3c63613678f7f85c2749205..54d71cbc2f621f7662bf943a691a19ed6285c9b9 100644 --- a/apps/desktopgui/src/router/configuration/PeerHelper.java +++ b/apps/desktopgui/src/router/configuration/PeerHelper.java @@ -160,6 +160,6 @@ public class PeerHelper { public final static String PROP_I2NP_INTERNAL_UDP_PORT = "i2np.udp.internalPort"; public final static String PROP_I2NP_NTCP_HOSTNAME = "i2np.ntcp.hostname"; public final static String PROP_I2NP_NTCP_PORT = "i2np.ntcp.port"; - public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoip"; - public final static String PROP_I2NP_NTCP_AUTO_IP = "i2np.ntcp.autoport"; + public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoport"; + public final static String PROP_I2NP_NTCP_AUTO_IP = "i2np.ntcp.autoip"; } diff --git a/apps/i2psnark/java/build.xml b/apps/i2psnark/java/build.xml index 9689fda06823a17019d39cd05c3488b19a433d70..d70233ac6e9404d541addc9993c7a86d6fca7491 100644 --- a/apps/i2psnark/java/build.xml +++ b/apps/i2psnark/java/build.xml @@ -24,6 +24,7 @@ </classpath> </depend> </target> + <property name="javac.compilerargs" value="" /> <target name="compile" depends="depend"> <mkdir dir="./build" /> <mkdir dir="./build/obj" /> @@ -31,7 +32,9 @@ srcdir="./src" debug="true" deprecation="on" source="1.5" target="1.5" destdir="./build/obj" - classpath="../../../core/java/build/i2p.jar:../../jetty/jettylib/org.mortbay.jetty.jar:../../jetty/jettylib/javax.servlet.jar:../../ministreaming/java/build/mstreaming.jar" /> + classpath="../../../core/java/build/i2p.jar:../../jetty/jettylib/org.mortbay.jetty.jar:../../jetty/jettylib/javax.servlet.jar:../../ministreaming/java/build/mstreaming.jar" > + <compilerarg line="${javac.compilerargs}" /> + </javac> </target> <target name="jar" depends="builddep, compile"> <jar destfile="./build/i2psnark.jar" basedir="./build/obj" includes="**/*.class" excludes="**/*Servlet.class"> @@ -55,6 +58,7 @@ <target name="standalone_prep" depends="war"> <javac debug="true" deprecation="on" source="1.5" target="1.5" destdir="./build" srcdir="src/" includes="org/klomp/snark/web/RunStandalone.java" > + <compilerarg line="${javac.compilerargs}" /> <classpath> <pathelement location="../../jetty/jettylib/commons-logging.jar" /> <pathelement location="../../jetty/jettylib/commons-el.jar" /> diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerMonitorTask.java b/apps/i2psnark/java/src/org/klomp/snark/PeerMonitorTask.java index 229391cd71f804c394ac3047515f9428c72c2db6..3ee8932f61f1653d5ba9dc3143fdd5c833001ee7 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerMonitorTask.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerMonitorTask.java @@ -23,6 +23,8 @@ package org.klomp.snark; import java.util.Iterator; import java.util.TimerTask; +import net.i2p.data.DataHelper; + /** * TimerTask that monitors the peers and total up/download speeds. * Works together with the main Snark class to report periodical statistics. @@ -83,21 +85,12 @@ class PeerMonitorTask extends TimerTask // Print some statistics long downloaded = coordinator.getDownloaded(); - String totalDown; - if (downloaded >= 10 * 1024 * 1024) - totalDown = (downloaded / (1024 * 1024)) + "MB"; - else - totalDown = (downloaded / 1024 )+ "KB"; + String totalDown = DataHelper.formatSize(downloaded) + "B"; long uploaded = coordinator.getUploaded(); - String totalUp; - if (uploaded >= 10 * 1024 * 1024) - totalUp = (uploaded / (1024 * 1024)) + "MB"; - else - totalUp = (uploaded / 1024) + "KB"; + String totalUp = DataHelper.formatSize(uploaded) + "B"; int needP = coordinator.storage.needed(); - long needMB - = needP * coordinator.metainfo.getPieceLength(0) / (1024 * 1024); + long needMB = needP * coordinator.metainfo.getPieceLength(0) / (1024 * 1024); int totalP = coordinator.metainfo.getPieces(); long totalMB = coordinator.metainfo.getTotalLength() / (1024 * 1024); diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java index 054b58262b3ed013db52214738a6f76766cad0e5..378cd8758c94dbed20080b2fc6e2fd40c1ffe4b0 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java @@ -60,9 +60,9 @@ class PeerState // If we have te resend outstanding requests (true after we got choked). private boolean resend = false; - private final static int MAX_PIPELINE = 3; // this is for outbound requests + private final static int MAX_PIPELINE = 5; // this is for outbound requests private final static int MAX_PIPELINE_BYTES = 128*1024; // this is for inbound requests - public final static int PARTSIZE = 32*1024; // Snark was 16K, i2p-bt uses 64KB + public final static int PARTSIZE = 16*1024; // outbound request private final static int MAX_PARTSIZE = 64*1024; // Don't let anybody request more than this PeerState(Peer peer, PeerListener listener, MetaInfo metainfo, diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index 60c44f3d5976fa2a9fa9d805757d8e2e42261be6..a45bf5161a76958a28a9834a456e1a068de35dc1 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -362,7 +362,7 @@ public class SnarkManager implements Snark.CompleteListener { public Properties getConfig() { return _config; } /** hardcoded for sanity. perhaps this should be customizable, for people who increase their ulimit, etc. */ - private static final int MAX_FILES_PER_TORRENT = 256; + private static final int MAX_FILES_PER_TORRENT = 512; /** set of filenames that we are dealing with */ public Set listTorrentFiles() { synchronized (_snarks) { return new HashSet(_snarks.keySet()); } } @@ -543,16 +543,18 @@ public class SnarkManager implements Snark.CompleteListener { return "Too many files in " + info.getName() + " (" + files.size() + "), deleting it"; } else if (info.getPieces() <= 0) { return "No pieces in " + info.getName() + "? deleting it"; - } else if (info.getPieceLength(0) > 1*1024*1024) { - return "Pieces are too large in " + info.getName() + " (" + info.getPieceLength(0)/1024 + "KB), deleting it"; - } else if (info.getTotalLength() > 10*1024*1024*1024l) { + } else if (info.getPieceLength(0) > Storage.MAX_PIECE_SIZE) { + return "Pieces are too large in " + info.getName() + " (" + DataHelper.formatSize(info.getPieceLength(0)) + + "B), deleting it"; + } else if (info.getTotalLength() > Storage.MAX_TOTAL_SIZE) { System.out.println("torrent info: " + info.toString()); List lengths = info.getLengths(); if (lengths != null) for (int i = 0; i < lengths.size(); i++) System.out.println("File " + i + " is " + lengths.get(i) + " long"); - return "Torrents larger than 10GB are not supported yet (because we're paranoid): " + info.getName() + ", deleting it"; + return "Torrents larger than " + DataHelper.formatSize(Storage.MAX_TOTAL_SIZE) + + "B are not supported yet (because we're paranoid): " + info.getName() + ", deleting it"; } else { // ok return null; @@ -637,8 +639,7 @@ public class SnarkManager implements Snark.CompleteListener { public void torrentComplete(Snark snark) { File f = new File(snark.torrent); long len = snark.meta.getTotalLength(); - addMessage("Download complete of " + f.getName() - + (len < 5*1024*1024 ? " (size: " + (len/1024) + "KB)" : " (size: " + (len/(1024*1024l)) + "MB)")); + addMessage("Download complete of " + f.getName() + " (size: " + DataHelper.formatSize(len) + "B)"); updateStatus(snark); } @@ -694,6 +695,7 @@ public class SnarkManager implements Snark.CompleteListener { // , "mastertracker", "http://VzXD~stRKbL3MOmeTn1iaCQ0CFyTmuFHiKYyo0Rd~dFPZFCYH-22rT8JD7i-C2xzYFa4jT5U2aqHzHI-Jre4HL3Ri5hFtZrLk2ax3ji7Qfb6qPnuYkuiF2E2UDmKUOppI8d9Ye7tjdhQVCy0izn55tBaB-U7UWdcvSK2i85sauyw3G0Gfads1Rvy5-CAe2paqyYATcDmGjpUNLoxbfv9KH1KmwRTNH6k1v4PyWYYnhbT39WfKMbBjSxVQRdi19cyJrULSWhjxaQfJHeWx5Z8Ev4bSPByBeQBFl2~4vqy0S5RypINsRSa3MZdbiAAyn5tr5slWR6QdoqY3qBQgBJFZppy-3iWkFqqKgSxCPundF8gdDLC5ddizl~KYcYKl42y9SGFHIukH-TZs8~em0~iahzsqWVRks3zRG~tlBcX2U3M2~OJs~C33-NKhyfZT7-XFBREvb8Szmd~p66jDxrwOnKaku-G6DyoQipJqIz4VHmY9-y5T8RrUcJcM-5lVoMpAAAA.i2p/announce.php=http://tracker.mastertracker.i2p/" // , "Galen", "http://5jpwQMI5FT303YwKa5Rd38PYSX04pbIKgTaKQsWbqoWjIfoancFdWCShXHLI5G5ofOb0Xu11vl2VEMyPsg1jUFYSVnu4-VfMe3y4TKTR6DTpetWrnmEK6m2UXh91J5DZJAKlgmO7UdsFlBkQfR2rY853-DfbJtQIFl91tbsmjcA5CGQi4VxMFyIkBzv-pCsuLQiZqOwWasTlnzey8GcDAPG1LDcvfflGV~6F5no9mnuisZPteZKlrv~~TDoXTj74QjByWc4EOYlwqK8sbU9aOvz~s31XzErbPTfwiawiaZ0RUI-IDrKgyvmj0neuFTWgjRGVTH8bz7cBZIc3viy6ioD-eMQOrXaQL0TCWZUelRwHRvgdPiQrxdYQs7ixkajeHzxi-Pq0EMm5Vbh3j3Q9kfUFW3JjFDA-MLB4g6XnjCbM5J1rC0oOBDCIEfhQkszru5cyLjHiZ5yeA0VThgu~c7xKHybv~OMXION7V8pBKOgET7ZgAkw1xgYe3Kkyq5syAAAA.i2p/tr/announce.php=http://galen.i2p/tr/" , "crstrack", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/" + , "Postman2", "http://lnQ6yoBTxQuQU8EQ1FlF395ITIQF-HGJxUeFvzETLFnoczNjQvKDbtSB7aHhn853zjVXrJBgwlB9sO57KakBDaJ50lUZgVPhjlI19TgJ-CxyHhHSCeKx5JzURdEW-ucdONMynr-b2zwhsx8VQCJwCEkARvt21YkOyQDaB9IdV8aTAmP~PUJQxRwceaTMn96FcVenwdXqleE16fI8CVFOV18jbJKrhTOYpTtcZKV4l1wNYBDwKgwPx5c0kcrRzFyw5~bjuAKO~GJ5dR7BQsL7AwBoQUS4k1lwoYrG1kOIBeDD3XF8BWb6K3GOOoyjc1umYKpur3G~FxBuqtHAsDRICkEbKUqJ9mPYQlTSujhNxiRIW-oLwMtvayCFci99oX8MvazPS7~97x0Gsm-onEK1Td9nBdmq30OqDxpRtXBimbzkLbR1IKObbg9HvrKs3L-kSyGwTUmHG9rSQSoZEvFMA-S0EXO~o4g21q1oikmxPMhkeVwQ22VHB0-LZJfmLr4SAAAA.i2p/announce.php=http://tracker2.postman.i2p/" }; /** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */ diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index 69e5a198f56a5117b800c44200554b9937f60811..51b4f97ebb67776c353070279af35ab057418368 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -56,10 +56,11 @@ public class Storage boolean changed; /** The default piece size. */ - private static int MIN_PIECE_SIZE = 256*1024; - private static int MAX_PIECE_SIZE = 1024*1024; + private static final int MIN_PIECE_SIZE = 256*1024; + public static final int MAX_PIECE_SIZE = 1024*1024; /** The maximum number of pieces in a torrent. */ - private static long MAX_PIECES = 100*1024/20; + public static final int MAX_PIECES = 10*1024; + public static final long MAX_TOTAL_SIZE = MAX_PIECE_SIZE * (long) MAX_PIECES; /** * Creates a new storage based on the supplied MetaInfo. This will diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java index 52e10957396f18211db30057d87dd886b2d3361d..515594219e378dcd246b52d4415c76b254d5e5ba 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -502,9 +502,10 @@ public class I2PSnarkServlet extends HttpServlet { out.write(filename); if (remaining == 0) out.write("</a>"); - // temporarily hardcoded for postman and anonymity, requires bytemonsoon patch for lookup by info_hash + // temporarily hardcoded for postman* and anonymity, requires bytemonsoon patch for lookup by info_hash String announce = snark.meta.getAnnounce(); - if (announce.startsWith("http://YRgrgTLG") || announce.startsWith("http://8EoJZIKr")) { + if (announce.startsWith("http://YRgrgTLG") || announce.startsWith("http://8EoJZIKr") || + announce.startsWith("http://lnQ6yoBT")) { Map trackers = _manager.getTrackers(); for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) { Map.Entry entry = (Map.Entry)iter.next(); diff --git a/apps/i2ptunnel/java/build.xml b/apps/i2ptunnel/java/build.xml index 564f6fc4b85b3e75aad91dcf58ec90e882e88291..5ab73d5e2f5bca78f7aca2b519f71e3b3a88e06a 100644 --- a/apps/i2ptunnel/java/build.xml +++ b/apps/i2ptunnel/java/build.xml @@ -22,6 +22,7 @@ </classpath> </depend> </target> + <property name="javac.compilerargs" value="" /> <target name="compile" depends="depend"> <mkdir dir="./build" /> <mkdir dir="./build/obj" /> @@ -29,7 +30,9 @@ srcdir="./src" debug="true" deprecation="on" source="1.5" target="1.5" destdir="./build/obj" - classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" /> + classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" > + <compilerarg line="${javac.compilerargs}" /> + </javac> </target> <target name="jar" depends="builddep, compile"> <jar destfile="./build/i2ptunnel.jar" basedir="./build/obj" includes="**/*.class"> @@ -73,6 +76,7 @@ </java> <javac debug="true" deprecation="on" source="1.5" target="1.5" destdir="../jsp/WEB-INF/classes/" srcdir="../jsp/WEB-INF/classes" includes="**/*.java"> + <compilerarg line="${javac.compilerargs}" /> <classpath> <pathelement location="../../jetty/jettylib/jasper-runtime.jar" /> <pathelement location="../../jetty/jettylib/javax.servlet.jar" /> diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java index d781866d95f4edf8d94138d3990006f470c40d82..9e102aa9858b5ac265cdd3d4aba8a7ffe5aca8e1 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java @@ -122,7 +122,7 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna } if (wwwProxy != null) { - StringTokenizer tok = new StringTokenizer(wwwProxy, ","); + StringTokenizer tok = new StringTokenizer(wwwProxy, ", "); while (tok.hasMoreTokens()) _proxyList.add(tok.nextToken().trim()); } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java index 277328363ee5d4d6bffccf0750a3e6b4a0fbdd10..53c3136b20f86a6d5c5a6053ffe2350859ff7f6b 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java @@ -152,7 +152,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable } if (wwwProxy != null) { - StringTokenizer tok = new StringTokenizer(wwwProxy, ","); + StringTokenizer tok = new StringTokenizer(wwwProxy, ", "); while (tok.hasMoreTokens()) proxyList.add(tok.nextToken().trim()); } diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java index 8b62702198213b321a3d73bcdc86a321f84dc223..3b5bff785d08377ee6a326e96a4f5d3a0f4c2049 100644 --- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java +++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java @@ -46,7 +46,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable notifyThis, "IRCHandler " + (++__clientId), tunnel, pkf); - StringTokenizer tok = new StringTokenizer(destinations, ","); + StringTokenizer tok = new StringTokenizer(destinations, ", "); dests = new ArrayList(1); while (tok.hasMoreTokens()) { String destination = tok.nextToken(); diff --git a/apps/jetty/build.xml b/apps/jetty/build.xml index 643dd79fdcb77b1c908ef84be030b3b654224e60..dab064c5ec24b3f403bd747d0a1824f4945e7f0d 100644 --- a/apps/jetty/build.xml +++ b/apps/jetty/build.xml @@ -6,6 +6,7 @@ <property name="jetty.url" value="http://dist.codehaus.org/jetty/jetty-5.1.x/jetty-5.1.12.zip" /> <property name="jetty.filename" value="jetty-5.1.12.zip" /> <property name="verified.filename" value="verified.txt" /> + <property name="javac.compilerargs" value="" /> <target name="all" depends="build" /> @@ -90,9 +91,11 @@ <mkdir dir="./build/obj" /> <javac srcdir="./java/src" - debug="true" deprecation="on" source="1.5" target="1.5" + debug="true" source="1.5" target="1.5" destdir="./build/obj" - classpath="./jettylib/commons-logging.jar:./jettylib/javax.servlet.jar:./jettylib/org.mortbay.jetty.jar" /> + classpath="./jettylib/commons-logging.jar:./jettylib/javax.servlet.jar:./jettylib/org.mortbay.jetty.jar" > + <compilerarg line="${javac.compilerargs}" /> + </javac> </target> <target name="jar" depends="compile"> <jar destfile="./jettylib/org.mortbay.jetty.jar" basedir="./build/obj" includes="**/*.class" update="true" > diff --git a/apps/jetty/java/src/org/mortbay/http/HttpContext.java b/apps/jetty/java/src/org/mortbay/http/HttpContext.java new file mode 100644 index 0000000000000000000000000000000000000000..061d3ad17f971f853ebc3216bef59952bbcbc329 --- /dev/null +++ b/apps/jetty/java/src/org/mortbay/http/HttpContext.java @@ -0,0 +1,2198 @@ +// ======================================================================== +// $Id: HttpContext.java,v 1.136 2006/02/21 09:47:43 gregwilkins Exp $ +// Copyright 2000-2004 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== + +package org.mortbay.http; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.Socket; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.UnknownHostException; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Permissions; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import org.apache.commons.logging.Log; +import org.mortbay.log.LogFactory; +import org.mortbay.http.ResourceCache.ResourceMetaData; +import org.mortbay.http.handler.ErrorPageHandler; +import org.mortbay.util.Container; +import org.mortbay.util.EventProvider; +import org.mortbay.util.IO; +import org.mortbay.util.LazyList; +import org.mortbay.util.LifeCycle; +import org.mortbay.util.LogSupport; +import org.mortbay.util.MultiException; +import org.mortbay.util.Resource; +import org.mortbay.util.URI; + + +/* ------------------------------------------------------------ */ +/** Context for a collection of HttpHandlers. + * HTTP Context provides an ordered container for HttpHandlers + * that share the same path prefix, filebase, resourcebase and/or + * classpath. + * <p> + * A HttpContext is analagous to a ServletContext in the + * Servlet API, except that it may contain other types of handler + * other than servlets. + * <p> + * A ClassLoader is created for the context and it uses + * Thread.currentThread().getContextClassLoader(); as it's parent loader. + * The class loader is initialized during start(), when a derived + * context calls initClassLoader() or on the first call to loadClass() + * <p> + * + * <B>Note. that order is important when configuring a HttpContext. + * For example, if resource serving is enabled before servlets, then resources + * take priority.</B> + * + * @see HttpServer + * @see HttpHandler + * @see org.mortbay.jetty.servlet.ServletHttpContext + * @version $Id: HttpContext.java,v 1.136 2006/02/21 09:47:43 gregwilkins Exp $ + * @author Greg Wilkins (gregw) + */ +public class HttpContext extends Container + implements LifeCycle, + HttpHandler, + EventProvider, + Serializable +{ + private static Log log = LogFactory.getLog(HttpContext.class); + + /* ------------------------------------------------------------ */ + /** File class path attribute. + * If this name is set as a context init parameter, then the attribute + * name given will be used to set the file classpath for the context as a + * context attribute. + */ + public final static String __fileClassPathAttr= + "org.mortbay.http.HttpContext.FileClassPathAttribute"; + + public final static String __ErrorHandler= + "org.mortbay.http.ErrorHandler"; + + + /* ------------------------------------------------------------ */ + /* ------------------------------------------------------------ */ + // These attributes are serialized by WebApplicationContext, which needs + // to be updated if you add to these + private String _contextPath; + private List _vhosts=new ArrayList(2); + private List _hosts=new ArrayList(2); + private List _handlers=new ArrayList(3); + private Map _attributes = new HashMap(3); + private boolean _redirectNullPath=true; + private boolean _statsOn=false; + private PermissionCollection _permissions; + private boolean _classLoaderJava2Compliant=true; + private ResourceCache _resources; + private String[] _systemClasses=new String [] {"java.","javax.servlet.","javax.xml.","org.mortbay.","org.xml.","org.w3c.","org.apache.commons.logging."}; + private String[] _serverClasses = new String[] {"-org.mortbay.http.PathMap","-org.mortbay.jetty.servlet.Invoker","-org.mortbay.jetty.servlet.JSR154Filter","-org.mortbay.jetty.servlet.Default","org.mortbay.jetty.Server","org.mortbay.http.","org.mortbay.start.","org.mortbay.stop."}; + + /* ------------------------------------------------------------ */ + private String _contextName; + private String _classPath; + private Map _initParams = new HashMap(11); + private UserRealm _userRealm; + private String _realmName; + private PathMap _constraintMap=new PathMap(); + private Authenticator _authenticator; + private RequestLog _requestLog; + + + private String[] _welcomes= + { + "welcome.html", + "index.html", + "index.htm", + "index.jsp" + }; + + + /* ------------------------------------------------------------ */ + private transient boolean _gracefulStop; + private transient ClassLoader _parent; + private transient ClassLoader _loader; + private transient HttpServer _httpServer; + private transient File _tmpDir; + private transient HttpHandler[] _handlersArray; + private transient String[] _vhostsArray; + + + /* ------------------------------------------------------------ */ + transient Object _statsLock=new Object[0]; + transient long _statsStartedAt; + transient int _requests; + transient int _requestsActive; + transient int _requestsActiveMax; + transient int _responses1xx; // Informal + transient int _responses2xx; // Success + transient int _responses3xx; // Redirection + transient int _responses4xx; // Client Error + transient int _responses5xx; // Server Error + + + /* ------------------------------------------------------------ */ + /** Constructor. + */ + public HttpContext() + { + setAttribute(__ErrorHandler, new ErrorPageHandler()); + _resources=new ResourceCache(); + addComponent(_resources); + } + + /* ------------------------------------------------------------ */ + /** Constructor. + * @param httpServer + * @param contextPathSpec + */ + public HttpContext(HttpServer httpServer,String contextPathSpec) + { + this(); + setHttpServer(httpServer); + setContextPath(contextPathSpec); + } + + /* ------------------------------------------------------------ */ + private void readObject(java.io.ObjectInputStream in) + throws IOException, ClassNotFoundException + { + in.defaultReadObject(); + _statsLock=new Object[0]; + getHandlers(); + for (int i=0;i<_handlersArray.length;i++) + _handlersArray[i].initialize(this); + } + + /* ------------------------------------------------------------ */ + /** Get the ThreadLocal HttpConnection. + * Get the HttpConnection for current thread, if any. This method is + * not static in order to control access. + * @return HttpConnection for this thread. + */ + public HttpConnection getHttpConnection() + { + return HttpConnection.getHttpConnection(); + } + + /* ------------------------------------------------------------ */ + void setHttpServer(HttpServer httpServer) + { + _httpServer=httpServer; + _contextName=null; + + } + + /* ------------------------------------------------------------ */ + public HttpServer getHttpServer() + { + return _httpServer; + } + + /* ------------------------------------------------------------ */ + public void setStopGracefully(boolean graceful) + { + _gracefulStop=graceful; + } + + /* ------------------------------------------------------------ */ + public boolean getStopGracefully() + { + return _gracefulStop; + } + + + /* ------------------------------------------------------------ */ + public static String canonicalContextPathSpec(String contextPathSpec) + { + // check context path + if (contextPathSpec==null || + contextPathSpec.indexOf(',')>=0 || + contextPathSpec.startsWith("*")) + throw new IllegalArgumentException ("Illegal context spec:"+contextPathSpec); + + if(!contextPathSpec.startsWith("/")) + contextPathSpec='/'+contextPathSpec; + + if (contextPathSpec.length()>1) + { + if (contextPathSpec.endsWith("/")) + contextPathSpec+="*"; + else if (!contextPathSpec.endsWith("/*")) + contextPathSpec+="/*"; + } + + return contextPathSpec; + } + + /* ------------------------------------------------------------ */ + public void setContextPath(String contextPathSpec) + { + if (_httpServer!=null) + _httpServer.removeMappings(this); + + contextPathSpec=canonicalContextPathSpec(contextPathSpec); + + if (contextPathSpec.length()>1) + _contextPath=contextPathSpec.substring(0,contextPathSpec.length()-2); + else + _contextPath="/"; + + _contextName=null; + + if (_httpServer!=null) + _httpServer.addMappings(this); + } + + + /* ------------------------------------------------------------ */ + /** + * @return The context prefix + */ + public String getContextPath() + { + return _contextPath; + } + + + /* ------------------------------------------------------------ */ + /** Add a virtual host alias to this context. + * @see #setVirtualHosts + * @param hostname A hostname. A null host name means any hostname is + * acceptable. Host names may String representation of IP addresses. + */ + public void addVirtualHost(String hostname) + { + // Note that null hosts are also added. + if (!_vhosts.contains(hostname)) + { + _vhosts.add(hostname); + _contextName=null; + + if (_httpServer!=null) + { + if (_vhosts.size()==1) + _httpServer.removeMapping(null,this); + _httpServer.addMapping(hostname,this); + } + _vhostsArray=null; + } + } + + /* ------------------------------------------------------------ */ + /** remove a virtual host alias to this context. + * @see #setVirtualHosts + * @param hostname A hostname. A null host name means any hostname is + * acceptable. Host names may String representation of IP addresses. + */ + public void removeVirtualHost(String hostname) + { + // Note that null hosts are also added. + if (_vhosts.remove(hostname)) + { + _contextName=null; + if (_httpServer!=null) + { + _httpServer.removeMapping(hostname,this); + if (_vhosts.size()==0) + _httpServer.addMapping(null,this); + } + _vhostsArray=null; + } + } + + /* ------------------------------------------------------------ */ + /** Set the virtual hosts for the context. + * Only requests that have a matching host header or fully qualified + * URL will be passed to that context with a virtual host name. + * A context with no virtual host names or a null virtual host name is + * available to all requests that are not served by a context with a + * matching virtual host name. + * @param hosts Array of virtual hosts that this context responds to. A + * null host name or null/empty array means any hostname is acceptable. + * Host names may String representation of IP addresses. + */ + public void setVirtualHosts(String[] hosts) + { + List old = new ArrayList(_vhosts); + + if (hosts!=null) + { + for (int i=0;i<hosts.length;i++) + { + boolean existing=old.remove(hosts[i]); + if (!existing) + addVirtualHost(hosts[i]); + } + } + + for (int i=0;i<old.size();i++) + removeVirtualHost((String)old.get(i)); + } + + /* ------------------------------------------------------------ */ + /** Get the virtual hosts for the context. + * Only requests that have a matching host header or fully qualified + * URL will be passed to that context with a virtual host name. + * A context with no virtual host names or a null virtual host name is + * available to all requests that are not served by a context with a + * matching virtual host name. + * @return Array of virtual hosts that this context responds to. A + * null host name or empty array means any hostname is acceptable. + * Host names may be String representation of IP addresses. + */ + public String[] getVirtualHosts() + { + if (_vhostsArray!=null) + return _vhostsArray; + if (_vhosts==null) + _vhostsArray=new String[0]; + else + { + _vhostsArray=new String[_vhosts.size()]; + _vhostsArray=(String[])_vhosts.toArray(_vhostsArray); + } + return _vhostsArray; + } + + + /* ------------------------------------------------------------ */ + /** Set the hosts for the context. + * Set the real hosts that this context will accept requests for. + * If not null or empty, then only requests from HttpListeners for hosts + * in this array are accepted by this context. + * Unlike virutal hosts, this value is not used by HttpServer for + * matching a request to a context. + */ + public void setHosts(String[] hosts) + throws UnknownHostException + { + if (hosts==null || hosts.length==0) + _hosts=null; + else + { + _hosts=new ArrayList(); + for (int i=0;i<hosts.length;i++) + if (hosts[i]!=null) + _hosts.add(InetAddress.getByName(hosts[i])); + } + + } + + /* ------------------------------------------------------------ */ + /** Get the hosts for the context. + */ + public String[] getHosts() + { + if (_hosts==null || _hosts.size()==0) + return null; + String[] hosts=new String[_hosts.size()]; + for (int i=0;i<hosts.length;i++) + { + InetAddress a = (InetAddress)_hosts.get(i); + if (a!=null) + hosts[i]=a.getHostName(); + } + return hosts; + } + + + /* ------------------------------------------------------------ */ + /** Set system classes. + * System classes cannot be overriden by context classloaders. + * @param classes array of classname Strings. Names ending with '.' are treated as package names. Names starting with '-' are treated as + * negative matches and must be listed before any enclosing packages. + */ + public void setSystemClasses(String[] classes) + { + _systemClasses=classes; + } + + /* ------------------------------------------------------------ */ + /** Get system classes. + * System classes cannot be overriden by context classloaders. + * @return array of classname Strings. Names ending with '.' are treated as package names. Names starting with '-' are treated as + * negative matches and must be listed before any enclosing packages. Null if not set. + */ + public String[] getSystemClasses() + { + return _systemClasses; + } + + + /* ------------------------------------------------------------ */ + /** Set system classes. + * Servers classes cannot be seen by context classloaders. + * @param classes array of classname Strings. Names ending with '.' are treated as package names. Names starting with '-' are treated as + * negative matches and must be listed before any enclosing packages. + */ + public void setServerClasses(String[] classes) + { + _serverClasses=classes; + } + + /* ------------------------------------------------------------ */ + /** Get system classes. + * System classes cannot be seen by context classloaders. + * @return array of classname Strings. Names ending with '.' are treated as package names. Names starting with '-' are treated as + * negative matches and must be listed before any enclosing packages. Null if not set. + */ + public String[] getServerClasses() + { + return _serverClasses; + } + + + /* ------------------------------------------------------------ */ + public void setHandlers(HttpHandler[] handlers) + { + List old = new ArrayList(_handlers); + + if (handlers!=null) + { + for (int i=0;i<handlers.length;i++) + { + boolean existing=old.remove(handlers[i]); + if (!existing) + addHandler(handlers[i]); + } + } + + for (int i=0;i<old.size();i++) + removeHandler((HttpHandler)old.get(i)); + } + + /* ------------------------------------------------------------ */ + /** Get all handlers. + * @return List of all HttpHandlers + */ + public HttpHandler[] getHandlers() + { + if (_handlersArray!=null) + return _handlersArray; + if (_handlers==null) + _handlersArray=new HttpHandler[0]; + else + { + _handlersArray=new HttpHandler[_handlers.size()]; + _handlersArray=(HttpHandler[])_handlers.toArray(_handlersArray); + } + return _handlersArray; + } + + + /* ------------------------------------------------------------ */ + /** Add a handler. + * @param i The position in the handler list + * @param handler The handler. + */ + public synchronized void addHandler(int i,HttpHandler handler) + { + _handlers.add(i,handler); + _handlersArray=null; + + HttpContext context = handler.getHttpContext(); + if (context==null) + handler.initialize(this); + else if (context!=this) + throw new IllegalArgumentException("Handler in another HttpContext"); + addComponent(handler); + } + + /* ------------------------------------------------------------ */ + /** Add a HttpHandler to the context. + * @param handler + */ + public synchronized void addHandler(HttpHandler handler) + { + addHandler(_handlers.size(),handler); + } + + /* ------------------------------------------------------------ */ + /** Get handler index. + * @param handler instance + * @return Index of handler in context or -1 if not found. + */ + public int getHandlerIndex(HttpHandler handler) + { + for (int h=0;h<_handlers.size();h++) + { + if ( handler == _handlers.get(h)) + return h; + } + return -1; + } + + /* ------------------------------------------------------------ */ + /** Get a handler by class. + * @param handlerClass + * @return The first handler that is an instance of the handlerClass + */ + public synchronized HttpHandler getHandler(Class handlerClass) + { + for (int h=0;h<_handlers.size();h++) + { + HttpHandler handler = (HttpHandler)_handlers.get(h); + if (handlerClass.isInstance(handler)) + return handler; + } + return null; + } + + /* ------------------------------------------------------------ */ + /** Remove a handler. + * The handler must be stopped before being removed. + * @param i index of handler + */ + public synchronized HttpHandler removeHandler(int i) + { + HttpHandler handler = _handlersArray[i]; + if (handler.isStarted()) + try{handler.stop();} catch (InterruptedException e){log.warn(LogSupport.EXCEPTION,e);} + _handlers.remove(i); + _handlersArray=null; + removeComponent(handler); + return handler; + } + + /* ------------------------------------------------------------ */ + /** Remove a handler. + * The handler must be stopped before being removed. + */ + public synchronized void removeHandler(HttpHandler handler) + { + if (handler.isStarted()) + try{handler.stop();} catch (InterruptedException e){log.warn(LogSupport.EXCEPTION,e);} + _handlers.remove(handler); + removeComponent(handler); + _handlersArray=null; + } + + + /* ------------------------------------------------------------ */ + /** Set context init parameter. + * Init Parameters differ from attributes as they can only + * have string values, servlets cannot set them and they do + * not have a package scoped name space. + * @param param param name + * @param value param value or null + */ + public void setInitParameter(String param, String value) + { + _initParams.put(param,value); + } + + /* ------------------------------------------------------------ */ + /** Get context init parameter. + * @param param param name + * @return param value or null + */ + public String getInitParameter(String param) + { + return (String)_initParams.get(param); + } + + /* ------------------------------------------------------------ */ + /** Get context init parameter. + * @return Enumeration of names + */ + public Enumeration getInitParameterNames() + { + return Collections.enumeration(_initParams.keySet()); + } + + /* ------------------------------------------------------------ */ + /** Set a context attribute. + * @param name attribute name + * @param value attribute value + */ + public synchronized void setAttribute(String name, Object value) + { + _attributes.put(name,value); + } + + /* ------------------------------------------------------------ */ + /** + * @param name attribute name + * @return attribute value or null + */ + public Object getAttribute(String name) + { + return _attributes.get(name); + } + + /* ------------------------------------------------------------ */ + /** + */ + public Map getAttributes() + { + return _attributes; + } + + /* ------------------------------------------------------------ */ + /** + */ + public void setAttributes(Map attributes) + { + _attributes=attributes; + } + + /* ------------------------------------------------------------ */ + /** + * @return enumaration of names. + */ + public Enumeration getAttributeNames() + { + return Collections.enumeration(_attributes.keySet()); + } + + /* ------------------------------------------------------------ */ + /** + * @param name attribute name + */ + public synchronized void removeAttribute(String name) + { + _attributes.remove(name); + } + + + /* ------------------------------------------------------------ */ + public void flushCache() + { + _resources.flushCache(); + } + + /* ------------------------------------------------------------ */ + public String[] getWelcomeFiles() + { + return _welcomes; + } + + /* ------------------------------------------------------------ */ + public void setWelcomeFiles(String[] welcomes) + { + if (welcomes==null) + _welcomes=new String[0]; + else + _welcomes=welcomes; + } + + /* ------------------------------------------------------------ */ + public void addWelcomeFile(String welcomeFile) + { + if (welcomeFile.startsWith("/") || + welcomeFile.startsWith(java.io.File.separator) || + welcomeFile.endsWith("/") || + welcomeFile.endsWith(java.io.File.separator)) + log.warn("Invalid welcome file: "+welcomeFile); + List list = new ArrayList(Arrays.asList(_welcomes)); + list.add(welcomeFile); + _welcomes=(String[])list.toArray(_welcomes); + } + + /* ------------------------------------------------------------ */ + public void removeWelcomeFile(String welcomeFile) + { + List list = new ArrayList(Arrays.asList(_welcomes)); + list.remove(welcomeFile); + _welcomes=(String[])list.toArray(_welcomes); + } + + /* ------------------------------------------------------------ */ + public String getWelcomeFile(Resource resource) + throws IOException + { + if (!resource.isDirectory()) + return null; + + for (int i=0;i<_welcomes.length;i++) + { + Resource welcome=resource.addPath(_welcomes[i]); + if (welcome.exists()) + return _welcomes[i]; + } + + return null; + } + + + /* ------------------------------------------------------------ */ + /** Get the context classpath. + * This method only returns the paths that have been set for this + * context and does not include any paths from a parent or the + * system classloader. + * Note that this may not be a legal javac classpath. + * @return a comma or ';' separated list of class + * resources. These may be jar files, directories or URLs to jars + * or directories. + * @see #getFileClassPath() + */ + public String getClassPath() + { + return _classPath; + } + + /* ------------------------------------------------------------ */ + /** Get the file classpath of the context. + * This method makes a best effort to return a complete file + * classpath for the context. + * It is obtained by walking the classloader hierarchy and looking for + * URLClassLoaders. The system property java.class.path is also checked for + * file elements not already found in the loader hierarchy. + * @return Path of files and directories for loading classes. + * @exception IllegalStateException HttpContext.initClassLoader + * has not been called. + */ + public String getFileClassPath() + throws IllegalStateException + { + + ClassLoader loader = getClassLoader(); + if (loader==null) + throw new IllegalStateException("Context classloader not initialized"); + + LinkedList paths =new LinkedList(); + LinkedList loaders=new LinkedList(); + + // Walk the loader hierarchy + while (loader !=null) + { + loaders.add(0,loader); + loader = loader.getParent(); + } + + // Try to handle java2compliant modes + loader=getClassLoader(); + if (loader instanceof ContextLoader && !((ContextLoader)loader).isJava2Compliant()) + { + loaders.remove(loader); + loaders.add(0,loader); + } + + for (int i=0;i<loaders.size();i++) + { + loader=(ClassLoader)loaders.get(i); + + if (log.isDebugEnabled()) log.debug("extract paths from "+loader); + if (loader instanceof URLClassLoader) + { + URL[] urls = ((URLClassLoader)loader).getURLs(); + for (int j=0;urls!=null && j<urls.length;j++) + { + try + { + Resource path = Resource.newResource(urls[j]); + if (log.isTraceEnabled()) log.trace("path "+path); + File file = path.getFile(); + if (file!=null) + paths.add(file.getAbsolutePath()); + } + catch(Exception e) + { + LogSupport.ignore(log,e); + } + } + } + } + + // Add the system classpath elements from property. + String jcp=System.getProperty("java.class.path"); + if (jcp!=null) + { + StringTokenizer tok=new StringTokenizer(jcp,File.pathSeparator); + while (tok.hasMoreTokens()) + { + String path=tok.nextToken(); + if (!paths.contains(path)) + { + if(log.isTraceEnabled())log.trace("PATH="+path); + paths.add(path); + } + else + if(log.isTraceEnabled())log.trace("done="+path); + } + } + + StringBuffer buf = new StringBuffer(); + Iterator iter = paths.iterator(); + while(iter.hasNext()) + { + if (buf.length()>0) + buf.append(File.pathSeparator); + buf.append(iter.next().toString()); + } + + if (log.isDebugEnabled()) log.debug("fileClassPath="+buf); + return buf.toString(); + } + + /* ------------------------------------------------------------ */ + /** Sets the class path for the context. + * A class path is only required for a context if it uses classes + * that are not in the system class path. + * @param classPath a comma or ';' separated list of class + * resources. These may be jar files, directories or URLs to jars + * or directories. + */ + public void setClassPath(String classPath) + { + _classPath=classPath; + if (isStarted()) + log.warn("classpath set while started"); + } + + /* ------------------------------------------------------------ */ + /** Add the class path element to the context. + * A class path is only required for a context if it uses classes + * that are not in the system class path. + * @param classPath a comma or ';' separated list of class + * resources. These may be jar files, directories or URLs to jars + * or directories. + */ + public void addClassPath(String classPath) + { + if (_classPath==null || _classPath.length()==0) + _classPath=classPath; + else + _classPath+=","+classPath; + + if (isStarted()) + log.warn("classpath set while started"); + } + + /* ------------------------------------------------------------ */ + /** Add elements to the class path for the context from the jar and zip files found + * in the specified resource. + * @param lib the resource that contains the jar and/or zip files. + * @param append true if the classpath entries are to be appended to any + * existing classpath, or false if they replace the existing classpath. + * @see #setClassPath(String) + */ + public void addClassPaths(Resource lib) + { + if (isStarted()) + log.warn("classpaths set while started"); + + if (lib.exists() && lib.isDirectory()) + { + String[] files=lib.list(); + for (int f=0;files!=null && f<files.length;f++) + { + try { + Resource fn=lib.addPath(files[f]); + String fnlc=fn.getName().toLowerCase(); + if (fnlc.endsWith(".jar") || fnlc.endsWith(".zip")) + { + addClassPath(fn.toString()); + } + } + catch (Exception ex) + { + log.warn(LogSupport.EXCEPTION,ex); + } + } + } + } + + /* ------------------------------------------------------------ */ + /** Get Java2 compliant classloading. + * @return If true, the class loader will conform to the java 2 + * specification and delegate all loads to the parent classloader. If + * false, the context classloader only delegate loads for system classes + * or classes that it can't find itself. + */ + public boolean isClassLoaderJava2Compliant() + { + return _classLoaderJava2Compliant; + } + + /* ------------------------------------------------------------ */ + /** Set Java2 compliant classloading. + * @param compliant If true, the class loader will conform to the java 2 + * specification and delegate all loads to the parent classloader. If + * false, the context classloader only delegate loads for system classes + * or classes that it can't find itself. + */ + public void setClassLoaderJava2Compliant(boolean compliant) + { + _classLoaderJava2Compliant = compliant; + if (_loader!=null && (_loader instanceof ContextLoader)) + ((ContextLoader)_loader).setJava2Compliant(compliant); + } + + /* ------------------------------------------------------------ */ + /** Set temporary directory for context. + * The javax.servlet.context.tempdir attribute is also set. + * @param dir Writable temporary directory. + */ + public void setTempDirectory(File dir) + { + if (isStarted()) + throw new IllegalStateException("Started"); + + if (dir!=null) + { + try{dir=new File(dir.getCanonicalPath());} + catch (IOException e){log.warn(LogSupport.EXCEPTION,e);} + } + + if (dir!=null && !dir.exists()) + { + dir.mkdir(); + dir.deleteOnExit(); + } + + if (dir!=null && ( !dir.exists() || !dir.isDirectory() || !dir.canWrite())) + throw new IllegalArgumentException("Bad temp directory: "+dir); + + _tmpDir=dir; + setAttribute("javax.servlet.context.tempdir",_tmpDir); + } + + /* ------------------------------------------------------------ */ + /** Get Context temporary directory. + * A tempory directory is generated if it has not been set. The + * "javax.servlet.context.tempdir" attribute is consulted and if + * not set, the host, port and context are used to generate a + * directory within the JVMs temporary directory. + * + * Patched for IPV6 support in I2P to replace ':' in the dir name which + * Windows can't handle. + * + * @return Temporary directory as a File. + */ + public File getTempDirectory() + { + if (_tmpDir!=null) + return _tmpDir; + + // Initialize temporary directory + // + // I'm afraid that this is very much black magic. + // but if you can think of better.... + Object t = getAttribute("javax.servlet.context.tempdir"); + + if (t!=null && (t instanceof File)) + { + _tmpDir=(File)t; + if (_tmpDir.isDirectory() && _tmpDir.canWrite()) + return _tmpDir; + } + + if (t!=null && (t instanceof String)) + { + try + { + _tmpDir=new File((String)t); + + if (_tmpDir.isDirectory() && _tmpDir.canWrite()) + { + if(log.isDebugEnabled())log.debug("Converted to File "+_tmpDir+" for "+this); + setAttribute("javax.servlet.context.tempdir",_tmpDir); + return _tmpDir; + } + } + catch(Exception e) + { + log.warn(LogSupport.EXCEPTION,e); + } + } + + // No tempdir so look for a WEB-INF/work directory to use as tempDir base + File work=null; + try + { + work=new File(System.getProperty("jetty.home"),"work"); + if (!work.exists() || !work.canWrite() || !work.isDirectory()) + work=null; + } + catch(Exception e) + { + LogSupport.ignore(log,e); + } + + // No tempdir set so make one! + try + { + HttpListener httpListener=_httpServer.getListeners()[0]; + + String vhost = null; + for (int h=0;vhost==null && _vhosts!=null && h<_vhosts.size();h++) + vhost=(String)_vhosts.get(h); + String host=httpListener.getHost(); + String temp="Jetty_"+ + (host==null?"":host)+ + "_"+ + httpListener.getPort()+ + "_"+ + (vhost==null?"":vhost)+ + getContextPath(); + + temp=temp.replace('/','_'); + temp=temp.replace('.','_'); + temp=temp.replace('\\','_'); + temp=temp.replace(':','_'); + + + if (work!=null) + _tmpDir=new File(work,temp); + else + { + _tmpDir=new File(System.getProperty("java.io.tmpdir"),temp); + + if (_tmpDir.exists()) + { + if(log.isDebugEnabled())log.debug("Delete existing temp dir "+_tmpDir+" for "+this); + if (!IO.delete(_tmpDir)) + { + if(log.isDebugEnabled())log.debug("Failed to delete temp dir "+_tmpDir); + } + + if (_tmpDir.exists()) + { + String old=_tmpDir.toString(); + _tmpDir=File.createTempFile(temp+"_",""); + if (_tmpDir.exists()) + _tmpDir.delete(); + log.warn("Can't reuse "+old+", using "+_tmpDir); + } + } + } + + if (!_tmpDir.exists()) + _tmpDir.mkdir(); + if (work==null) + _tmpDir.deleteOnExit(); + if(log.isDebugEnabled())log.debug("Created temp dir "+_tmpDir+" for "+this); + } + catch(Exception e) + { + _tmpDir=null; + LogSupport.ignore(log,e); + } + + if (_tmpDir==null) + { + try{ + // that didn't work, so try something simpler (ish) + _tmpDir=File.createTempFile("JettyContext",""); + if (_tmpDir.exists()) + _tmpDir.delete(); + _tmpDir.mkdir(); + _tmpDir.deleteOnExit(); + if(log.isDebugEnabled())log.debug("Created temp dir "+_tmpDir+" for "+this); + } + catch(IOException e) + { + log.fatal(e); System.exit(1); + } + } + + setAttribute("javax.servlet.context.tempdir",_tmpDir); + return _tmpDir; + } + + + + /* ------------------------------------------------------------ */ + /** Set ClassLoader. + * @param loader The loader to be used by this context. + */ + public synchronized void setClassLoader(ClassLoader loader) + { + if (isStarted()) + throw new IllegalStateException("Started"); + _loader=loader; + } + + + /* ------------------------------------------------------------ */ + /** Get the classloader. + * If no classloader has been set and the context has been loaded + * normally, then null is returned. + * If no classloader has been set and the context was loaded from + * a classloader, that loader is returned. + * If a classloader has been set and no classpath has been set then + * the set classloader is returned. + * If a classloader and a classpath has been set, then a new + * URLClassloader initialized on the classpath with the set loader as a + * partent is return. + * @return Classloader or null. + */ + public synchronized ClassLoader getClassLoader() + { + return _loader; + } + + /* ------------------------------------------------------------ */ + /** Set Parent ClassLoader. + * By default the parent loader is the thread context classloader + * of the thread that calls initClassLoader. If setClassLoader is + * called, then the parent is ignored. + * @param loader The class loader to use for the parent loader of + * the context classloader. + */ + public synchronized void setParentClassLoader(ClassLoader loader) + { + if (isStarted()) + throw new IllegalStateException("Started"); + _parent=loader; + } + + /* ------------------------------------------------------------ */ + public ClassLoader getParentClassLoader() + { + return _parent; + } + + /* ------------------------------------------------------------ */ + /** Initialize the context classloader. + * Initialize the context classloader with the current parameters. + * Any attempts to change the classpath after this call will + * result in a IllegalStateException + * @param forceContextLoader If true, a ContextLoader is always if + * no loader has been set. + */ + protected void initClassLoader(boolean forceContextLoader) + throws MalformedURLException, IOException + { + ClassLoader parent=_parent; + if (_loader==null) + { + // If no parent, then try this threads classes loader as parent + if (parent==null) + parent=Thread.currentThread().getContextClassLoader(); + + // If no parent, then try this classes loader as parent + if (parent==null) + parent=this.getClass().getClassLoader(); + + if(log.isDebugEnabled())log.debug("Init classloader from "+_classPath+ + ", "+parent+" for "+this); + + if (forceContextLoader || _classPath!=null || _permissions!=null) + { + ContextLoader loader=new ContextLoader(this,_classPath,parent,_permissions); + loader.setJava2Compliant(_classLoaderJava2Compliant); + _loader=loader; + } + else + _loader=parent; + } + } + + /* ------------------------------------------------------------ */ + public synchronized Class loadClass(String className) + throws ClassNotFoundException + { + if (_loader==null) + { + try{initClassLoader(false);} + catch(Exception e) + { + log.warn(LogSupport.EXCEPTION,e); + return null; + } + } + + if (className==null) + return null; + + if (_loader == null) + return Class.forName(className); + return _loader.loadClass(className); + } + + /* ------------------------------------------------------------ */ + /** Set the realm name. + * @param realmName The name to use to retrieve the actual realm + * from the HttpServer + */ + public void setRealmName(String realmName) + { + _realmName=realmName; + } + + /* ------------------------------------------------------------ */ + public String getRealmName() + { + return _realmName; + } + + /* ------------------------------------------------------------ */ + /** Set the realm. + */ + public void setRealm(UserRealm realm) + { + _userRealm=realm; + } + + /* ------------------------------------------------------------ */ + public UserRealm getRealm() + { + return _userRealm; + } + + /* ------------------------------------------------------------ */ + public Authenticator getAuthenticator() + { + return _authenticator; + } + + /* ------------------------------------------------------------ */ + public void setAuthenticator(Authenticator authenticator) + { + _authenticator=authenticator; + } + + /* ------------------------------------------------------------ */ + public void addSecurityConstraint(String pathSpec, SecurityConstraint sc) + { + Object scs = _constraintMap.get(pathSpec); + scs = LazyList.add(scs,sc); + _constraintMap.put(pathSpec,scs); + + if(log.isDebugEnabled())log.debug("added "+sc+" at "+pathSpec); + } + + /* ------------------------------------------------------------ */ + public void clearSecurityConstraints() + { + _constraintMap.clear(); + } + + /* ------------------------------------------------------------ */ + public boolean checkSecurityConstraints( + String pathInContext, + HttpRequest request, + HttpResponse response) + throws HttpException, IOException + { + UserRealm realm= getRealm(); + + List scss= _constraintMap.getMatches(pathInContext); + String pattern=null; + if (scss != null && scss.size() > 0) + { + Object constraints= null; + + // for each path match + // Add only constraints that have the correct method + // break if the matching pattern changes. This allows only + // constraints with matching pattern and method to be combined. + loop: + for (int m= 0; m < scss.size(); m++) + { + Map.Entry entry= (Map.Entry)scss.get(m); + Object scs= entry.getValue(); + String p=(String)entry.getKey(); + for (int c=0;c<LazyList.size(scs);c++) + { + SecurityConstraint sc=(SecurityConstraint)LazyList.get(scs,c); + if (!sc.forMethod(request.getMethod())) + continue; + + if (pattern!=null && !pattern.equals(p)) + break loop; + pattern=p; + constraints= LazyList.add(constraints, sc); + } + } + + return SecurityConstraint.check( + LazyList.getList(constraints), + _authenticator, + realm, + pathInContext, + request, + response); + } + request.setUserPrincipal(HttpRequest.__NOT_CHECKED); + return true; + } + + /* ------------------------------------------------------------ */ + /** Set null path redirection. + * @param b if true a /context request will be redirected to + * /context/ if there is not path in the context. + */ + public void setRedirectNullPath(boolean b) + { + _redirectNullPath=b; + } + + /* ------------------------------------------------------------ */ + /** + * @return True if a /context request is redirected to /context/ if + * there is not path in the context. + */ + public boolean isRedirectNullPath() + { + return _redirectNullPath; + } + + + + /* ------------------------------------------------------------ */ + /** Set the permissions to be used for this context. + * The collection of permissions set here are used for all classes + * loaded by this context. This is simpler that creating a + * security policy file, as not all code sources may be statically + * known. + * @param permissions + */ + public void setPermissions(PermissionCollection permissions) + { + _permissions=permissions; + } + + /* ------------------------------------------------------------ */ + /** Get the permissions to be used for this context. + */ + public PermissionCollection getPermissions() + { + return _permissions; + } + + /* ------------------------------------------------------------ */ + /** Add a permission to this context. + * The collection of permissions set here are used for all classes + * loaded by this context. This is simpler that creating a + * security policy file, as not all code sources may be statically + * known. + * @param permission + */ + public void addPermission(Permission permission) + { + if (_permissions==null) + _permissions=new Permissions(); + _permissions.add(permission); + } + + /* ------------------------------------------------------------ */ + /** Handler request. + * Determine the path within the context and then call + * handle(pathInContext,request,response). + * @param request + * @param response + * @return True if the request has been handled. + * @exception HttpException + * @exception IOException + */ + public void handle(HttpRequest request, + HttpResponse response) + throws HttpException, IOException + { + if (!isStarted() || _gracefulStop) + return; + + // reject requests by real host + if (_hosts!=null && _hosts.size()>0) + { + Object o = request.getHttpConnection().getConnection(); + if (o instanceof Socket) + { + Socket s=(Socket)o; + if (!_hosts.contains(s.getLocalAddress())) + { + if(log.isDebugEnabled())log.debug(s.getLocalAddress()+" not in "+_hosts); + return; + } + } + } + + // handle stats + if (_statsOn) + { + synchronized(_statsLock) + { + _requests++; + _requestsActive++; + if (_requestsActive>_requestsActiveMax) + _requestsActiveMax=_requestsActive; + } + } + + String pathInContext = URI.canonicalPath(request.getPath()); + if (pathInContext==null) + { + // Must be a bad request. + throw new HttpException(HttpResponse.__400_Bad_Request); + } + + if (_contextPath.length()>1) + pathInContext=pathInContext.substring(_contextPath.length()); + + if (_redirectNullPath && (pathInContext==null || + pathInContext.length()==0)) + { + StringBuffer buf=request.getRequestURL(); + buf.append("/"); + String q=request.getQuery(); + if (q!=null&&q.length()!=0) + buf.append("?"+q); + + response.sendRedirect(buf.toString()); + if (log.isDebugEnabled()) + log.debug(this+" consumed all of path "+ + request.getPath()+ + ", redirect to "+buf.toString()); + return; + } + + String pathParams=null; + int semi = pathInContext.lastIndexOf(';'); + if (semi>=0) + { + int pl = pathInContext.length()-semi; + String ep=request.getEncodedPath(); + if(';'==ep.charAt(ep.length()-pl)) + { + pathParams=pathInContext.substring(semi+1); + pathInContext=pathInContext.substring(0,semi); + } + } + + try + { + handle(pathInContext,pathParams,request,response); + } + finally + { + if (_userRealm!=null && request.hasUserPrincipal()) + _userRealm.disassociate(request.getUserPrincipal()); + } + } + + /* ------------------------------------------------------------ */ + /** Handler request. + * Call each HttpHandler until request is handled. + * @param pathInContext Path in context + * @param pathParams Path parameters such as encoded Session ID + * @param request + * @param response + * @return True if the request has been handled. + * @exception HttpException + * @exception IOException + */ + public void handle(String pathInContext, + String pathParams, + HttpRequest request, + HttpResponse response) + throws HttpException, IOException + { + Object old_scope= null; + try + { + old_scope= enterContextScope(request,response); + HttpHandler[] handlers= getHandlers(); + for (int k= 0; k < handlers.length; k++) + { + HttpHandler handler= handlers[k]; + if (handler == null) + { + handlers= getHandlers(); + k= -1; + continue; + } + if (!handler.isStarted()) + { + if (log.isDebugEnabled()) + log.debug(handler + " not started in " + this); + continue; + } + if (log.isDebugEnabled()) + log.debug("Handler " + handler); + handler.handle(pathInContext, pathParams, request, response); + if (request.isHandled()) + { + if (log.isDebugEnabled()) + log.debug("Handled by " + handler); + return; + } + } + return; + } + finally + { + leaveContextScope(request, response, old_scope); + } + } + + /* ------------------------------------------------------------ */ + /** Enter the context scope. + * This method is called (by handle or servlet dispatchers) to indicate that + * request handling is entering the scope of this context. The opaque scope object + * returned, should be passed to the leaveContextScope method. + */ + public Object enterContextScope(HttpRequest request, HttpResponse response) + { + // Save the thread context loader + Thread thread = Thread.currentThread(); + ClassLoader cl=thread.getContextClassLoader(); + HttpContext c=response.getHttpContext(); + + Scope scope=null; + if (cl!=HttpContext.class.getClassLoader() || c!=null) + { + scope=new Scope(); + scope._classLoader=cl; + scope._httpContext=c; + } + + if (_loader!=null) + thread.setContextClassLoader(_loader); + response.setHttpContext(this); + + return scope; + } + + /* ------------------------------------------------------------ */ + /** Leave the context scope. + * This method is called (by handle or servlet dispatchers) to indicate that + * request handling is leaveing the scope of this context. The opaque scope object + * returned by enterContextScope should be passed in. + */ + public void leaveContextScope(HttpRequest request, HttpResponse response,Object oldScope) + { + if (oldScope==null) + { + Thread.currentThread() + .setContextClassLoader(HttpContext.class.getClassLoader()); + response.setHttpContext(null); + } + else + { + Scope old = (Scope)oldScope; + Thread.currentThread().setContextClassLoader(old._classLoader); + response.setHttpContext(old._httpContext); + } + } + + + /* ------------------------------------------------------------ */ + public String getHttpContextName() + { + if (_contextName==null) + _contextName = (_vhosts.size()>1?(_vhosts.toString()+":"):"")+_contextPath; + return _contextName; + } + + /* ------------------------------------------------------------ */ + public void setHttpContextName(String s) + { + _contextName=s; + } + + /* ------------------------------------------------------------ */ + public String toString() + { + return "HttpContext["+getContextPath()+","+getHttpContextName()+"]"; + } + + /* ------------------------------------------------------------ */ + public String toString(boolean detail) + { + return "HttpContext["+getContextPath()+","+getHttpContextName()+"]" + + (detail?("="+_handlers):""); + } + + + /* ------------------------------------------------------------ */ + protected synchronized void doStart() + throws Exception + { + if (isStarted()) + return; + + if (_httpServer.getServerClasses()!=null) + _serverClasses=_httpServer.getServerClasses(); + if (_httpServer.getSystemClasses()!=null) + _systemClasses=_httpServer.getSystemClasses(); + + _resources.start(); + + statsReset(); + + if (_httpServer==null) + throw new IllegalStateException("No server for "+this); + + // start the context itself + _resources.getMimeMap(); + _resources.getEncodingMap(); + + // Setup realm + if (_userRealm==null && _authenticator!=null) + { + _userRealm=_httpServer.getRealm(_realmName); + if (_userRealm==null) + log.warn("No Realm: "+_realmName); + } + + // setup the context loader + initClassLoader(false); + + // Set attribute if needed + String attr = getInitParameter(__fileClassPathAttr); + if (attr!=null && attr.length()>0) + setAttribute(attr,getFileClassPath()); + + // Start the handlers + Thread thread = Thread.currentThread(); + ClassLoader lastContextLoader=thread.getContextClassLoader(); + try + { + if (_loader!=null) + thread.setContextClassLoader(_loader); + + if (_requestLog!=null) + _requestLog.start(); + + startHandlers(); + } + finally + { + thread.setContextClassLoader(lastContextLoader); + getHandlers(); + } + + } + + /* ------------------------------------------------------------ */ + /** Start the handlers. + * This is called by start after the classloader has been + * initialized and set as the thread context loader. + * It may be specialized to provide custom handling + * before any handlers are started. + * @exception Exception + */ + protected void startHandlers() + throws Exception + { + // Prepare a multi exception + MultiException mx = new MultiException(); + + Iterator handlers = _handlers.iterator(); + while(handlers.hasNext()) + { + HttpHandler handler=(HttpHandler)handlers.next(); + if (!handler.isStarted()) + try{handler.start();}catch(Exception e){mx.add(e);} + } + mx.ifExceptionThrow(); + } + + /* ------------------------------------------------------------ */ + /** Stop the context. + * @param graceful If true and statistics are on, then this method will wait + * for requestsActive to go to zero before calling stop() + */ + public void stop(boolean graceful) + throws InterruptedException + { + boolean gs=_gracefulStop; + try + { + _gracefulStop=true; + + // wait for all requests to complete. + while (graceful && _statsOn && _requestsActive>0 && _httpServer!=null) + try {Thread.sleep(100);} + catch (InterruptedException e){throw e;} + catch (Exception e){LogSupport.ignore(log,e);} + + stop(); + } + finally + { + _gracefulStop=gs; + } + } + + /* ------------------------------------------------------------ */ + /** Stop the context. + */ + protected void doStop() + throws Exception + { + if (_httpServer==null) + throw new InterruptedException("Destroy called"); + + synchronized(this) + { + // Notify the container for the stop + Thread thread = Thread.currentThread(); + ClassLoader lastContextLoader=thread.getContextClassLoader(); + try + { + if (_loader!=null) + thread.setContextClassLoader(_loader); + Iterator handlers = _handlers.iterator(); + while(handlers.hasNext()) + { + HttpHandler handler=(HttpHandler)handlers.next(); + if (handler.isStarted()) + { + try{handler.stop();} + catch(Exception e){log.warn(LogSupport.EXCEPTION,e);} + } + } + + if (_requestLog!=null) + _requestLog.stop(); + } + finally + { + thread.setContextClassLoader(lastContextLoader); + } + + // TODO this is a poor test + if (_loader instanceof ContextLoader) + { + ((ContextLoader)_loader).destroy(); + LogFactory.release(_loader); + } + + _loader=null; + } + _resources.flushCache(); + _resources.stop(); + } + + + /* ------------------------------------------------------------ */ + /** Destroy a context. + * Destroy a context and remove it from the HttpServer. The + * HttpContext must be stopped before it can be destroyed. + */ + public void destroy() + { + if (isStarted()) + throw new IllegalStateException("Started"); + + if (_httpServer!=null) + _httpServer.removeContext(this); + + _httpServer=null; + + if (_handlers!=null) + _handlers.clear(); + + _handlers=null; + _parent=null; + _loader=null; + if (_attributes!=null) + _attributes.clear(); + _attributes=null; + if (_initParams!=null) + _initParams.clear(); + _initParams=null; + if (_vhosts!=null) + _vhosts.clear(); + _vhosts=null; + _hosts=null; + _tmpDir=null; + + _permissions=null; + + removeComponent(_resources); + if (_resources!=null) + { + _resources.flushCache(); + if (_resources.isStarted()) + try{_resources.stop();}catch(Exception e){LogSupport.ignore(log,e);} + _resources.destroy(); + } + _resources=null; + + super.destroy(); + + } + + + /* ------------------------------------------------------------ */ + /** Set the request log. + * @param log RequestLog to use. + */ + public void setRequestLog(RequestLog log) + { + _requestLog=log; + } + + /* ------------------------------------------------------------ */ + public RequestLog getRequestLog() + { + return _requestLog; + } + + + /* ------------------------------------------------------------ */ + /** Send an error response. + * This method may be specialized to provide alternative error handling for + * errors generated by the container. The default implemenation calls HttpResponse.sendError + * @param response the response to send + * @param code The error code + * @param msg The message for the error or null for the default + * @throws IOException Problem sending response. + */ + public void sendError(HttpResponse response,int code,String msg) + throws IOException + { + response.sendError(code,msg); + } + + /* ------------------------------------------------------------ */ + /** Send an error response. + * This method obtains the responses context and call sendError for context specific + * error handling. + * @param response the response to send + * @param code The error code + * @param msg The message for the error or null for the default + * @throws IOException Problem sending response. + */ + public static void sendContextError(HttpResponse response,int code,String msg) + throws IOException + { + HttpContext context = response.getHttpContext(); + if (context!=null) + context.sendError(response,code,msg); + else + response.sendError(code,msg); + } + + /* ------------------------------------------------------------ */ + /** True set statistics recording on for this context. + * @param on If true, statistics will be recorded for this context. + */ + public void setStatsOn(boolean on) + { + log.info("setStatsOn "+on+" for "+this); + _statsOn=on; + statsReset(); + } + + /* ------------------------------------------------------------ */ + public boolean getStatsOn() {return _statsOn;} + + /* ------------------------------------------------------------ */ + public long getStatsOnMs() + {return _statsOn?(System.currentTimeMillis()-_statsStartedAt):0;} + + /* ------------------------------------------------------------ */ + public void statsReset() + { + synchronized(_statsLock) + { + if (_statsOn) + _statsStartedAt=System.currentTimeMillis(); + _requests=0; + _requestsActiveMax=_requestsActive; + _responses1xx=0; + _responses2xx=0; + _responses3xx=0; + _responses4xx=0; + _responses5xx=0; + } + } + + /* ------------------------------------------------------------ */ + /** + * @return Get the number of requests handled by this context + * since last call of statsReset(). If setStatsOn(false) then this + * is undefined. + */ + public int getRequests() {return _requests;} + + /* ------------------------------------------------------------ */ + /** + * @return Number of requests currently active. + * Undefined if setStatsOn(false). + */ + public int getRequestsActive() {return _requestsActive;} + + /* ------------------------------------------------------------ */ + /** + * @return Maximum number of active requests + * since statsReset() called. Undefined if setStatsOn(false). + */ + public int getRequestsActiveMax() {return _requestsActiveMax;} + + /* ------------------------------------------------------------ */ + /** + * @return Get the number of responses with a 2xx status returned + * by this context since last call of statsReset(). Undefined if + * if setStatsOn(false). + */ + public int getResponses1xx() {return _responses1xx;} + + /* ------------------------------------------------------------ */ + /** + * @return Get the number of responses with a 100 status returned + * by this context since last call of statsReset(). Undefined if + * if setStatsOn(false). + */ + public int getResponses2xx() {return _responses2xx;} + + /* ------------------------------------------------------------ */ + /** + * @return Get the number of responses with a 3xx status returned + * by this context since last call of statsReset(). Undefined if + * if setStatsOn(false). + */ + public int getResponses3xx() {return _responses3xx;} + + /* ------------------------------------------------------------ */ + /** + * @return Get the number of responses with a 4xx status returned + * by this context since last call of statsReset(). Undefined if + * if setStatsOn(false). + */ + public int getResponses4xx() {return _responses4xx;} + + /* ------------------------------------------------------------ */ + /** + * @return Get the number of responses with a 5xx status returned + * by this context since last call of statsReset(). Undefined if + * if setStatsOn(false). + */ + public int getResponses5xx() {return _responses5xx;} + + + /* ------------------------------------------------------------ */ + /** Log a request and response. + * Statistics are also collected by this method. + * @param request + * @param response + */ + public void log(HttpRequest request, + HttpResponse response, + int length) + { + if (_statsOn) + { + synchronized(_statsLock) + { + if (--_requestsActive<0) + _requestsActive=0; + + if (response!=null) + { + switch(response.getStatus()/100) + { + case 1: _responses1xx++;break; + case 2: _responses2xx++;break; + case 3: _responses3xx++;break; + case 4: _responses4xx++;break; + case 5: _responses5xx++;break; + } + } + } + } + + if (_requestLog!=null && + request!=null && + response!=null) + _requestLog.log(request,response,length); + else if (_httpServer!=null) + _httpServer.log(request,response,length); + } + + + + /* ------------------------------------------------------------ */ + /* Class to save scope of nested context calls + */ + private static class Scope + { + ClassLoader _classLoader; + HttpContext _httpContext; + } + + /* + * @see org.mortbay.http.HttpHandler#getName() + */ + public String getName() + { + return this.getContextPath(); + } + + /* + * @see org.mortbay.http.HttpHandler#getHttpContext() + */ + public HttpContext getHttpContext() + { + return this; + } + + /* + * @see org.mortbay.http.HttpHandler#initialize(org.mortbay.http.HttpContext) + */ + public void initialize(HttpContext context) + { + throw new UnsupportedOperationException(); + } + + + /** + * @return + */ + public Resource getBaseResource() + { + return _resources.getBaseResource(); + } + /** + * @param type + * @return + */ + public String getEncodingByMimeType(String type) + { + return _resources.getEncodingByMimeType(type); + } + /** + * @return + */ + public Map getEncodingMap() + { + return _resources.getEncodingMap(); + } + /** + * @return + */ + public int getMaxCachedFileSize() + { + return _resources.getMaxCachedFileSize(); + } + /** + * @return + */ + public int getMaxCacheSize() + { + return _resources.getMaxCacheSize(); + } + /** + * @param filename + * @return + */ + public String getMimeByExtension(String filename) + { + return _resources.getMimeByExtension(filename); + } + /** + * @return + */ + public Map getMimeMap() + { + return _resources.getMimeMap(); + } + /** + * @param pathInContext + * @return + * @throws IOException + */ + public Resource getResource(String pathInContext) throws IOException + { + return _resources.getResource(pathInContext); + } + /** + * @return + */ + public String getResourceBase() + { + return _resources.getResourceBase(); + } + /** + * @param resource + * @return + */ + public ResourceMetaData getResourceMetaData(Resource resource) + { + return _resources.getResourceMetaData(resource); + } + /** + * @param base + */ + public void setBaseResource(Resource base) + { + _resources.setBaseResource(base); + } + /** + * @param encodingMap + */ + public void setEncodingMap(Map encodingMap) + { + _resources.setEncodingMap(encodingMap); + } + /** + * @param maxCachedFileSize + */ + public void setMaxCachedFileSize(int maxCachedFileSize) + { + _resources.setMaxCachedFileSize(maxCachedFileSize); + } + /** + * @param maxCacheSize + */ + public void setMaxCacheSize(int maxCacheSize) + { + _resources.setMaxCacheSize(maxCacheSize); + } + /** + * @param mimeMap + */ + public void setMimeMap(Map mimeMap) + { + _resources.setMimeMap(mimeMap); + } + /** + * @param extension + * @param type + */ + public void setMimeMapping(String extension, String type) + { + _resources.setMimeMapping(extension, type); + } + /** + * @param resourceBase + */ + public void setResourceBase(String resourceBase) + { + _resources.setResourceBase(resourceBase); + } + /** + * @param mimeType + * @param encoding + */ + public void setTypeEncoding(String mimeType, String encoding) + { + _resources.setTypeEncoding(mimeType, encoding); + } +} diff --git a/apps/ministreaming/java/build.xml b/apps/ministreaming/java/build.xml index 48920deefef64ddbe54539c94f827c8587bc7743..1f83b640ddbe78e3ff8c8395f0372a56bdf31714 100644 --- a/apps/ministreaming/java/build.xml +++ b/apps/ministreaming/java/build.xml @@ -19,10 +19,13 @@ </classpath> </depend> </target> + <property name="javac.compilerargs" value="" /> <target name="compile" depends="depend"> <mkdir dir="./build" /> <mkdir dir="./build/obj" /> - <javac srcdir="./src" debug="true" deprecation="on" source="1.5" target="1.5" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar" /> + <javac srcdir="./src" debug="true" deprecation="on" source="1.5" target="1.5" destdir="./build/obj" classpath="../../../core/java/build/i2p.jar" > + <compilerarg line="${javac.compilerargs}" /> + </javac> </target> <target name="jar" depends="compile"> <jar destfile="./build/mstreaming.jar" basedir="./build/obj" includes="**/*.class" /> diff --git a/apps/routerconsole/java/build.xml b/apps/routerconsole/java/build.xml index 00168963bf50b1415bba70ef900cc176fee8889c..23e1ac05bdb955ea41cf575c8e66037877b1685b 100644 --- a/apps/routerconsole/java/build.xml +++ b/apps/routerconsole/java/build.xml @@ -40,6 +40,7 @@ <targetfilelist dir="." files="build/obj/net/i2p/router/web/UpdateHandler.class" /> </dependset> </target> + <property name="javac.compilerargs" value="" /> <target name="compile" depends="prepare, depend, dependVersion"> <mkdir dir="./build" /> <mkdir dir="./build/obj" /> @@ -47,6 +48,7 @@ srcdir="./src" debug="true" deprecation="on" source="1.5" target="1.5" destdir="./build/obj"> + <compilerarg line="${javac.compilerargs}" /> <classpath> <pathelement location="../../../core/java/build/i2p.jar" /> <pathelement location="../../../router/java/build/router.jar" /> @@ -114,6 +116,7 @@ <javac debug="true" deprecation="on" source="1.5" target="1.5" destdir="../jsp/WEB-INF/classes/" srcdir="../jsp/WEB-INF/classes" includes="**/*.java"> + <compilerarg line="${javac.compilerargs}" /> <classpath> <pathelement location="../../jetty/jettylib/jasper-runtime.jar" /> <pathelement location="../../jetty/jettylib/javax.servlet.jar" /> diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java index 9beeb33cf500b7183f0a9fd8237e74b3e0c5b5e8..5d7e412bf3dc5be8d61cfd1dd4f00848194c87d7 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java @@ -18,8 +18,8 @@ public class ConfigNetHelper extends HelperBase { public final static String PROP_I2NP_INTERNAL_UDP_PORT = "i2np.udp.internalPort"; public final static String PROP_I2NP_NTCP_HOSTNAME = "i2np.ntcp.hostname"; public final static String PROP_I2NP_NTCP_PORT = "i2np.ntcp.port"; - public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoip"; - public final static String PROP_I2NP_NTCP_AUTO_IP = "i2np.ntcp.autoport"; + public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoport"; + public final static String PROP_I2NP_NTCP_AUTO_IP = "i2np.ntcp.autoip"; public String getNtcphostname() { if (!TransportManager.enableNTCP(_context)) return "\" disabled=\"true"; diff --git a/apps/routerconsole/java/src/net/i2p/router/web/NetDbHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/NetDbHelper.java index a3280ac446c4af4ad3f29c1633103762e1f73a6e..886ba6abb6dda80e96c60a736ed444debf83a61e 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/NetDbHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/NetDbHelper.java @@ -10,17 +10,21 @@ import net.i2p.router.RouterContext; public class NetDbHelper extends HelperBase { private String _routerPrefix; private boolean _full = false; + private boolean _lease = false; public NetDbHelper() {} public void setRouter(String r) { _routerPrefix = r; } - public void setFull(String f) { _full = "1".equals(f); }; + public void setFull(String f) { _full = "1".equals(f); } + public void setLease(String l) { _lease = "1".equals(l); } public String getNetDbSummary() { try { if (_out != null) { if (_routerPrefix != null) _context.netDb().renderRouterInfoHTML(_out, _routerPrefix); + else if (_lease) + _context.netDb().renderLeaseSetHTML(_out); else _context.netDb().renderStatusHTML(_out, _full); return ""; @@ -28,6 +32,8 @@ public class NetDbHelper extends HelperBase { ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024); if (_routerPrefix != null) _context.netDb().renderRouterInfoHTML(new OutputStreamWriter(baos), _routerPrefix); + else if (_lease) + _context.netDb().renderLeaseSetHTML(new OutputStreamWriter(baos)); else _context.netDb().renderStatusHTML(new OutputStreamWriter(baos), _full); return new String(baos.toByteArray()); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java index 1b302ff0b92393ef4ca5866f06ca8c9f43354548..a275e2a612b790313cdde81fde1eb67d15dbb55c 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java @@ -364,7 +364,10 @@ public class SummaryHelper extends HelperBase { Destination client = (Destination)iter.next(); String name = getName(client); - buf.append("<b>*</b> ").append(name).append("<br />\n"); + buf.append("<b>*</b> "); + buf.append("<a href=\"tunnels.jsp#").append(client.calculateHash().toBase64().substring(0,4)); + buf.append("\" target=\"_top\" title=\"Show tunnels\">"); + buf.append(name).append("</a><br />\n"); LeaseSet ls = _context.netDb().lookupLeaseSetLocally(client.calculateHash()); if (ls != null) { long timeToExpire = ls.getEarliestLeaseDate() - _context.clock().now(); @@ -375,10 +378,6 @@ public class SummaryHelper extends HelperBase { } else { buf.append("<i>No leases</i><br />\n"); } - buf.append("<a href=\"tunnels.jsp#").append(client.calculateHash().toBase64().substring(0,4)); - buf.append("\" target=\"_top\">Details</a> "); - buf.append("<a href=\"configtunnels.jsp#").append(client.calculateHash().toBase64().substring(0,4)); - buf.append("\" target=\"_top\">Config</a><br />\n"); } buf.append("<hr />\n"); return buf.toString(); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/UpdateHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/UpdateHandler.java index 81f8d6e8d970c2836b24a5d2fb2fd87b1041d901..84d54263ea1bd503486dccca1e39b88051534ac3 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/UpdateHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/UpdateHandler.java @@ -92,14 +92,25 @@ public class UpdateHandler { return _updateRunner.getStatus(); } + public boolean isDone() { + if(this._updateRunner == null) + return true; + return this._updateRunner.isDone(); + } + public class UpdateRunner implements Runnable, EepGet.StatusListener { protected boolean _isRunning; + protected boolean done; protected String _status; public UpdateRunner() { - _isRunning = false; + _isRunning = false; + this.done = false; _status = "<b>Updating</b>"; } public boolean isRunning() { return _isRunning; } + public boolean isDone() { + return this.done; + } public String getStatus() { return _status; } public void run() { _isRunning = true; @@ -159,6 +170,7 @@ public class UpdateHandler { f.delete(); if (err == null) { String policy = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_POLICY); + this.done = true; if ("install".equals(policy)) { _log.log(Log.CRIT, "Update was VERIFIED, restarting to install it"); _status = "<b>Update verified</b><br />Restarting"; diff --git a/apps/routerconsole/jsp/config.jsp b/apps/routerconsole/jsp/config.jsp index ae357d69f1e7fd1965daa2b02d5925500df3d3e9..53c9192638b650d3f901ab50f52e0b754035e875 100644 --- a/apps/routerconsole/jsp/config.jsp +++ b/apps/routerconsole/jsp/config.jsp @@ -78,7 +78,7 @@ the <i>Status: Firewalled</i> line), or you can manually require them here. Users behind symmetric NATs, such as OpenBSD's pf, are not currently supported.</p> <input type="submit" name="recheckReachability" value="Check network reachability..." /> - <hr /> + <p> <b>Inbound TCP connection configuration:</b><br /> Externally reachable hostname or IP address: <input name ="ntcphost" type="text" size="16" value="<jsp:getProperty name="nethelper" property="ntcphostname" />" /> @@ -118,7 +118,13 @@ <li><b>Firewalled</b> - Your UDP port appears to be firewalled. As the firewall detection methods are not 100% reliable, this may occasionally be displayed in error. However, if it appears consistently, you should check whether both your external and internal - firewalls are open on port 8887. + firewalls are open on port 8887. I2P will work fine when firewalled, there is no reason for concern. + When firewalled, the router uses "introducers" to relay inbound connections. + However, you will get more participating traffic and help the network more if you can open your + firewall(s). If you think you have already done so, remember that you may have both a hardware + and a software firewall, or be behind an additional, institutional firewall you cannot control. + Also, some routers cannot correctly forward both TCP and UDP on a single port, or may have other + limitations or bugs that prevent them from passing traffic through to I2P. <li><b>Testing</b> - The router is currently testing whether your UDP port is firewalled. <li><b>Hidden</b> - The router is not configured to publish its address, therefore it does not expect incoming connections. @@ -142,7 +148,8 @@ <li><b>ERR - Private TCP Address</b> - You must never advertise an unroutable IP address such as 127.0.0.1 or 192.168.1.1 as your external address. Correct the address or disable inbound TCP above. <li><b>ERR - SymmetricNAT</b> - I2P detected that you are firewalled by a Symmetric NAT. - I2P does not work behind this type of firewall. + I2P does not work well behind this type of firewall. You will probably not be able to + accept inbound connections, which will limit your participation in the network. <li><b>ERR - UDP Port In Use - Set i2np.udp.internalPort=xxxx in advanced config and restart</b> - I2P was unable to bind to port 8887 or other configured port. Check to see if another program is using port 8887. If so, stop that program or configure diff --git a/apps/routerconsole/jsp/configlogging.jsp b/apps/routerconsole/jsp/configlogging.jsp index b660a15198d52f64a6a3e82c691bfb092b454d46..8f4c069e07ab43c9e2979ec8074db6583018dfc4 100644 --- a/apps/routerconsole/jsp/configlogging.jsp +++ b/apps/routerconsole/jsp/configlogging.jsp @@ -41,7 +41,9 @@ <hr /> <b>Log levels:</b> <br /> <b>Default log level:</b> - <jsp:getProperty name="logginghelper" property="defaultLogLevelBox" /><br /> + <jsp:getProperty name="logginghelper" property="defaultLogLevelBox" /> + <i>(DEBUG and INFO are not recommended defaults, as they will drastically slow down your router)</i> + <br /> <jsp:getProperty name="logginghelper" property="logLevelTable" /> <hr /> <input type="submit" name="shouldsave" value="Save changes" /> diff --git a/apps/routerconsole/jsp/default.css b/apps/routerconsole/jsp/default.css index 527a7c9bea4a947a9655e516fd0d696381c7e47d..d5d2fd48bb90d7e6d4dd18755a0fdf13857dbb4d 100644 --- a/apps/routerconsole/jsp/default.css +++ b/apps/routerconsole/jsp/default.css @@ -5,6 +5,7 @@ body { text-align: center; background-color: white; color: black; + font-size: 100%; } .hide { @@ -15,6 +16,11 @@ img { border: none; } +pre { + width: 100%; + overflow-x: scroll; +} + div.logo { float: left; width: 200px; @@ -30,23 +36,25 @@ div.toolbar { font-weight: bold; } -div.routersummary { - /* width: 8em; */ - /* height: 5em; */ - /* position: fixed; */ +div.routersummaryouter { float: left; - width: 200px; - /* left: 1em; */ - /* top: 1em; */ + width: 215px; + margin: 0; + padding: 0; + border: 0; + clear: left; /* fixes a bug in Opera */ + overflow: auto; +} + +div.routersummary { + background-color: #fafaff; + width: 195px; + color: inherit; margin: 0em; - padding: .5em; + padding: 5px; text-align: left; border: medium solid #efefff; - background-color: #fafaff; - color: inherit; - font-size: small; - clear: left; /* fixes a bug in Opera */ - overflow: auto; + font-size: 0.82em; } div.warning { @@ -67,6 +75,10 @@ div.main { color: inherit; } +div.main textarea { + width: 100% !important; +} + div.news { margin: 0em 1em 1em 224px; padding: .5em 1em; diff --git a/apps/routerconsole/jsp/logs.jsp b/apps/routerconsole/jsp/logs.jsp index 36d3562fe025c909cb07c483f48fb920660c2f60..a102912488fe59f56ab86d674260eecc053d662d 100644 --- a/apps/routerconsole/jsp/logs.jsp +++ b/apps/routerconsole/jsp/logs.jsp @@ -11,6 +11,14 @@ <%@include file="summary.jsp" %> <div class="main" id="main"> + <h4>Version:</h4><a name="version"> </a> + Please include this information in bug reports. + <p> +I2P <jsp:getProperty name="helper" property="version" /><br /> +<%=System.getProperty("java.vendor")%> <%=System.getProperty("java.version")%><br /> +<%=System.getProperty("os.name")%> <%=System.getProperty("os.arch")%> <%=System.getProperty("os.version")%><br /> + </p> + <hr /> <jsp:useBean class="net.i2p.router.web.LogsHelper" id="logsHelper" scope="request" /> <jsp:setProperty name="logsHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" /> <h4>Router logs:</h4> @@ -21,12 +29,6 @@ <hr /> <h4>Service (Wrapper) logs:</h4><a name="servicelogs"> </a> <jsp:getProperty name="logsHelper" property="serviceLogs" /> - <hr /> - <h4>Java Version:</h4><a name="version"> </a> - <pre> -<%=System.getProperty("java.vendor")%> <%=System.getProperty("java.version")%> -<%=System.getProperty("os.name")%> <%=System.getProperty("os.arch")%> <%=System.getProperty("os.version")%> - </pre> </div> </body> diff --git a/apps/routerconsole/jsp/netdb.jsp b/apps/routerconsole/jsp/netdb.jsp index 08a1377d37ff35a188da0076466dc0cc95e9b519..392888bc6728b136135565e180695a15a32882d3 100644 --- a/apps/routerconsole/jsp/netdb.jsp +++ b/apps/routerconsole/jsp/netdb.jsp @@ -16,6 +16,7 @@ <jsp:setProperty name="netdbHelper" property="writer" value="<%=out%>" /> <jsp:setProperty name="netdbHelper" property="full" value="<%=request.getParameter("f")%>" /> <jsp:setProperty name="netdbHelper" property="router" value="<%=request.getParameter("r")%>" /> + <jsp:setProperty name="netdbHelper" property="lease" value="<%=request.getParameter("l")%>" /> <jsp:getProperty name="netdbHelper" property="netDbSummary" /> </div> diff --git a/apps/routerconsole/jsp/summary.jsp b/apps/routerconsole/jsp/summary.jsp index 48f3b4fefd9e2c9dcd153cdb2d7f555105da2b46..4b7aaa908446e928636c28f4be9d37fdc902ee55 100644 --- a/apps/routerconsole/jsp/summary.jsp +++ b/apps/routerconsole/jsp/summary.jsp @@ -1,102 +1,30 @@ -<%@page import="net.i2p.router.web.SummaryHelper" %> -<jsp:useBean class="net.i2p.router.web.SummaryHelper" id="helper" scope="request" /> -<jsp:setProperty name="helper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" /> - -<jsp:useBean class="net.i2p.router.web.ReseedHandler" id="reseed" scope="request" /> -<jsp:setProperty name="reseed" property="*" /> -<jsp:useBean class="net.i2p.router.web.UpdateHandler" id="update" scope="request" /> -<jsp:setProperty name="update" property="*" /> -<jsp:setProperty name="update" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" /> -<jsp:useBean class="net.i2p.router.web.ConfigUpdateHelper" id="uhelper" scope="request" /> -<jsp:setProperty name="uhelper" property="*" /> -<jsp:setProperty name="uhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" /> - +<% // put width here too to prevent bad layout at startup %> +<div class="routersummaryouter" style="width: 215px;"> +<% + // skip the iframe if refresh disabled + String d = request.getParameter("refresh"); + String newDelay = ""; + if (d == null || "".equals(d)) + d = System.getProperty("routerconsole.summaryRefresh"); + else + // pass the new delay parameter to the iframe + newDelay = "?refresh=" + d; + if (!"0".equals(d)) + out.print("<iframe src=\"summaryframe.jsp" + newDelay + "\" height=\"1500\" width=\"100%\" scrolling=\"auto\" frameborder=\"0\" allowtransparency=\"true\">\n"); +%> <div class="routersummary"> - <center><b><a href="config.jsp">Configuration</a> <a href="help.jsp">Help</a></b></center> - <hr /> - - <u><b>General</b></u><br /> - <b>Ident:</b> (<a title="Your router identity is <jsp:getProperty name="helper" property="ident" />, never reveal it to anyone" href="netdb.jsp?r=.">view</a>)<br /> - <b>Version:</b> <jsp:getProperty name="helper" property="version" /><br /> - <b>Uptime:</b> <jsp:getProperty name="helper" property="uptime" /><br /> - <b>Now:</b> <jsp:getProperty name="helper" property="time" /><br /> - <b>Reachability:</b> <a href="config.jsp#help"><jsp:getProperty name="helper" property="reachability" /></a><% - if (helper.updateAvailable()) { - // display all the time so we display the final failure message - out.print("<br />" + update.getStatus()); - if ("true".equals(System.getProperty("net.i2p.router.web.UpdateHandler.updateInProgress", "false"))) { - } else { - long nonce = new java.util.Random().nextLong(); - String prev = System.getProperty("net.i2p.router.web.UpdateHandler.nonce"); - if (prev != null) System.setProperty("net.i2p.router.web.UpdateHandler.noncePrev", prev); - System.setProperty("net.i2p.router.web.UpdateHandler.nonce", nonce+""); - String uri = request.getRequestURI(); - out.print("<p><form action=\"" + uri + "\" method=\"GET\">\n"); - out.print("<input type=\"hidden\" name=\"updateNonce\" value=\"" + nonce + "\" >\n"); - out.print("<input type=\"submit\" value=\"Download " + uhelper.getUpdateVersion() + " Update\" ></form></p>\n"); - } +<%@include file="summarynoframe.jsp" %> +<% + // d defined above + if (!"0".equals(d)) { + out.print("</div></iframe>\n"); + } else { + // since we don't have an iframe this will reload the base page, and + // the new delay will be passed to the iframe above + out.print("<hr /><p><form action=\"" + request.getRequestURI() + "\" method=\"GET\">\n"); + out.print("<b>Refresh (s):</b> <input size=\"3\" type=\"text\" name=\"refresh\" value=\"60\" />\n"); + out.print("<button type=\"submit\">Enable</button>\n"); + out.print("</form></p></div>\n"); } - %> - <p> - <%=net.i2p.router.web.ConfigRestartBean.renderStatus(request.getRequestURI(), request.getParameter("action"), request.getParameter("consoleNonce"))%> - </p> - <hr /> - - <u><b><a href="peers.jsp">Peers</a></b></u><br /> - <b>Active:</b> <jsp:getProperty name="helper" property="activePeers" />/<jsp:getProperty name="helper" property="activeProfiles" /><br /> - <b>Fast:</b> <jsp:getProperty name="helper" property="fastPeers" /><br /> - <b>High capacity:</b> <jsp:getProperty name="helper" property="highCapacityPeers" /><br /> - <b>Well integrated:</b> <jsp:getProperty name="helper" property="wellIntegratedPeers" /><br /> - <b>Known:</b> <jsp:getProperty name="helper" property="allPeers" /><br /><% - if (helper.getActivePeers() <= 0) { - %><b><a href="config.jsp">check your NAT/firewall</a></b><br /><% - } - // If showing the reseed link is allowed - if (helper.allowReseed()) { - if ("true".equals(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress", "false"))) { - // While reseed occurring, show status message instead - out.print("<i>" + System.getProperty("net.i2p.router.web.ReseedHandler.statusMessage","") + "</i><br />"); - } else { - // While no reseed occurring, show reseed link - long nonce = new java.util.Random().nextLong(); - String prev = System.getProperty("net.i2p.router.web.ReseedHandler.nonce"); - if (prev != null) System.setProperty("net.i2p.router.web.ReseedHandler.noncePrev", prev); - System.setProperty("net.i2p.router.web.ReseedHandler.nonce", nonce+""); - String uri = request.getRequestURI(); - out.print("<p><form action=\"" + uri + "\" method=\"GET\">\n"); - out.print("<input type=\"hidden\" name=\"reseedNonce\" value=\"" + nonce + "\" >\n"); - out.print("<button type=\"submit\" >Reseed</button></form></p>\n"); - } - } - // If a new reseed ain't running, and the last reseed had errors, show error message - if ("false".equals(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress", "false"))) { - String reseedErrorMessage = System.getProperty("net.i2p.router.web.ReseedHandler.errorMessage",""); - if (reseedErrorMessage.length() > 0) { - out.print("<i>" + reseedErrorMessage + "</i><br />"); - } - } - %><hr /> - - <u><b><a href="config.jsp" title="Configure the bandwidth limits">Bandwidth in/out</a></b></u><br /> - <b>1s:</b> <jsp:getProperty name="helper" property="inboundSecondKBps" />/<jsp:getProperty name="helper" property="outboundSecondKBps" />KBps<br /> - <b>5m:</b> <jsp:getProperty name="helper" property="inboundFiveMinuteKBps" />/<jsp:getProperty name="helper" property="outboundFiveMinuteKBps" />KBps<br /> - <b>Total:</b> <jsp:getProperty name="helper" property="inboundLifetimeKBps" />/<jsp:getProperty name="helper" property="outboundLifetimeKBps" />KBps<br /> - <b>Used:</b> <jsp:getProperty name="helper" property="inboundTransferred" />/<jsp:getProperty name="helper" property="outboundTransferred" /><br /> - <hr /> - - <jsp:getProperty name="helper" property="destinations" /> - - <u><b>Tunnels in/out</b></u><br /> - <b>Exploratory:</b> <jsp:getProperty name="helper" property="inboundTunnels" />/<jsp:getProperty name="helper" property="outboundTunnels" /><br /> - <b>Client:</b> <jsp:getProperty name="helper" property="inboundClientTunnels" />/<jsp:getProperty name="helper" property="outboundClientTunnels" /><br /> - <b>Participating:</b> <jsp:getProperty name="helper" property="participatingTunnels" /><br /> - <hr /> - - <u><b>Congestion</b></u><br /> - <b>Job lag:</b> <jsp:getProperty name="helper" property="jobLag" /><br /> - <b>Message delay:</b> <jsp:getProperty name="helper" property="messageDelay" /><br /> - <b>Tunnel lag:</b> <jsp:getProperty name="helper" property="tunnelLag" /><br /> - <b>Handle backlog:</b> <jsp:getProperty name="helper" property="inboundBacklog" /><br /> - <b><jsp:getProperty name="helper" property="tunnelStatus" /></b><br /> - +%> </div> diff --git a/apps/routerconsole/jsp/summaryframe.jsp b/apps/routerconsole/jsp/summaryframe.jsp new file mode 100644 index 0000000000000000000000000000000000000000..627fe328c8ad5888d96c3bf464b029f1ca443680 --- /dev/null +++ b/apps/routerconsole/jsp/summaryframe.jsp @@ -0,0 +1,68 @@ +<%@page contentType="text/html"%> +<%@page pageEncoding="UTF-8"%> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> + +<% +/* + * All links in the summary bar must have target="_top" + * so they don't load in the iframe + */ +%> + +<html><head> +<title>Summary Bar</title> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<% + // try hard to avoid an error page in the iframe after shutdown + String action = request.getParameter("action"); + String d = request.getParameter("refresh"); + boolean shutdownSoon = "shutdownImmediate".equals(action) || "restartImmediate".equals(action); + if (!shutdownSoon) { + if (d == null || "".equals(d)) { + d = System.getProperty("routerconsole.summaryRefresh"); + if (d == null || "".equals(d)) + d = "60"; + } else { + System.setProperty("routerconsole.summaryRefresh", d); + } + // we probably don't get here if d == "0" since caught in summary.jsp, but just + // to be sure... + if (!"0".equals(d)) { + // doesn't work for restart or shutdown with no expl. tunnels, + // since the call to ConfigRestartBean.renderStatus() hasn't happened yet... + long timeleft = net.i2p.router.web.ConfigRestartBean.getRestartTimeRemaining(); + long delay = 60; + try { delay = Long.parseLong(d); } catch (NumberFormatException nfe) {} + if (delay*1000 < timeleft + 5000) + out.print("<meta http-equiv=\"refresh\" content=\"" + d + "\" />\n"); + else + shutdownSoon = true; + } + } +%> +<link rel="stylesheet" href="default.css" type="text/css" /> +</head> + +<body style="margin: 0;"> + +<div class="routersummary"> +<%@include file="summarynoframe.jsp" %> +<% + // d and shutdownSoon defined above + if (!shutdownSoon) { + out.print("<hr /><p><form action=\"summaryframe.jsp\" method=\"GET\">\n"); + if ("0".equals(d)) { + out.print("<b>Refresh (s):<b> <input size=\"3\" type=\"text\" name=\"refresh\" value=\"60\" />\n"); + out.print("<button type=\"submit\">Enable</button>\n"); + } else { + // this will load in the iframe but subsequent pages will not have the iframe + out.print("<input type=\"hidden\" name=\"refresh\" value=\"0\" />\n"); + out.print("<button type=\"submit\">Disable " + d + "s Refresh</button>\n"); + } + out.print("</form></p>\n"); + } +%> +</div> + +</body> +</html> diff --git a/apps/routerconsole/jsp/summarynoframe.jsp b/apps/routerconsole/jsp/summarynoframe.jsp new file mode 100644 index 0000000000000000000000000000000000000000..f3f8b800246fa7f02d8dede10c92cba8dbd92708 --- /dev/null +++ b/apps/routerconsole/jsp/summarynoframe.jsp @@ -0,0 +1,100 @@ +<%@page import="net.i2p.router.web.SummaryHelper" %> +<jsp:useBean class="net.i2p.router.web.SummaryHelper" id="helper" scope="request" /> +<jsp:setProperty name="helper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" /> + +<jsp:useBean class="net.i2p.router.web.ReseedHandler" id="reseed" scope="request" /> +<jsp:setProperty name="reseed" property="*" /> +<jsp:useBean class="net.i2p.router.web.UpdateHandler" id="update" scope="request" /> +<jsp:setProperty name="update" property="*" /> +<jsp:setProperty name="update" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" /> +<jsp:useBean class="net.i2p.router.web.ConfigUpdateHelper" id="uhelper" scope="request" /> +<jsp:setProperty name="uhelper" property="*" /> +<jsp:setProperty name="uhelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" /> + + <center><b><a href="config.jsp" target="_top">Configuration</a> <a href="help.jsp" target="_top">Help</a></b></center> + <hr /> + + <u><b>General</b></u><br /> + <b>Ident:</b> (<a title="Your router identity is <jsp:getProperty name="helper" property="ident" />, never reveal it to anyone" href="netdb.jsp?r=." target="_top">view</a>)<br /> + <b>Version:</b> <jsp:getProperty name="helper" property="version" /><br /> + <b>Uptime:</b> <jsp:getProperty name="helper" property="uptime" /><br /> + <b>Now:</b> <jsp:getProperty name="helper" property="time" /><br /> + <b>Reachability:</b> <a href="config.jsp#help" target="_top"><jsp:getProperty name="helper" property="reachability" /></a><% + if (helper.updateAvailable()) { + // display all the time so we display the final failure message + out.print("<br />" + update.getStatus()); + if ("true".equals(System.getProperty("net.i2p.router.web.UpdateHandler.updateInProgress", "false"))) { + } else if(!update.isDone()) { + long nonce = new java.util.Random().nextLong(); + String prev = System.getProperty("net.i2p.router.web.UpdateHandler.nonce"); + if (prev != null) System.setProperty("net.i2p.router.web.UpdateHandler.noncePrev", prev); + System.setProperty("net.i2p.router.web.UpdateHandler.nonce", nonce+""); + String uri = request.getRequestURI(); + out.print("<p><form action=\"" + uri + "\" method=\"GET\">\n"); + out.print("<input type=\"hidden\" name=\"updateNonce\" value=\"" + nonce + "\" />\n"); + out.print("<input type=\"submit\" value=\"Download " + uhelper.getUpdateVersion() + " Update\" /></form></p>\n"); + } + } + %> + <p> + <%=net.i2p.router.web.ConfigRestartBean.renderStatus(request.getRequestURI(), request.getParameter("action"), request.getParameter("consoleNonce"))%> + </p> + <hr /> + + <u><b><a href="peers.jsp" target="_top">Peers</a></b></u><br /> + <b>Active:</b> <jsp:getProperty name="helper" property="activePeers" />/<jsp:getProperty name="helper" property="activeProfiles" /><br /> + <b>Fast:</b> <jsp:getProperty name="helper" property="fastPeers" /><br /> + <b>High capacity:</b> <jsp:getProperty name="helper" property="highCapacityPeers" /><br /> + <b>Well integrated:</b> <jsp:getProperty name="helper" property="wellIntegratedPeers" /><br /> + <b>Known:</b> <jsp:getProperty name="helper" property="allPeers" /><br /><% + if (helper.getActivePeers() <= 0) { + %><b><a href="config.jsp" target="_top">check your NAT/firewall</a></b><br /><% + } + // If showing the reseed link is allowed + if (helper.allowReseed()) { + if ("true".equals(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress", "false"))) { + // While reseed occurring, show status message instead + out.print("<i>" + System.getProperty("net.i2p.router.web.ReseedHandler.statusMessage","") + "</i><br />"); + } else { + // While no reseed occurring, show reseed link + long nonce = new java.util.Random().nextLong(); + String prev = System.getProperty("net.i2p.router.web.ReseedHandler.nonce"); + if (prev != null) System.setProperty("net.i2p.router.web.ReseedHandler.noncePrev", prev); + System.setProperty("net.i2p.router.web.ReseedHandler.nonce", nonce+""); + String uri = request.getRequestURI(); + out.print("<p><form action=\"" + uri + "\" method=\"GET\">\n"); + out.print("<input type=\"hidden\" name=\"reseedNonce\" value=\"" + nonce + "\" />\n"); + out.print("<button type=\"submit\" >Reseed</button></form></p>\n"); + } + } + // If a new reseed ain't running, and the last reseed had errors, show error message + if ("false".equals(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress", "false"))) { + String reseedErrorMessage = System.getProperty("net.i2p.router.web.ReseedHandler.errorMessage",""); + if (reseedErrorMessage.length() > 0) { + out.print("<i>" + reseedErrorMessage + "</i><br />"); + } + } + %><hr /> + + <u><b><a href="config.jsp" title="Configure the bandwidth limits" target="_top">Bandwidth in/out</a></b></u><br /> + <b>1s:</b> <jsp:getProperty name="helper" property="inboundSecondKBps" />/<jsp:getProperty name="helper" property="outboundSecondKBps" />KBps<br /> + <b>5m:</b> <jsp:getProperty name="helper" property="inboundFiveMinuteKBps" />/<jsp:getProperty name="helper" property="outboundFiveMinuteKBps" />KBps<br /> + <b>Total:</b> <jsp:getProperty name="helper" property="inboundLifetimeKBps" />/<jsp:getProperty name="helper" property="outboundLifetimeKBps" />KBps<br /> + <b>Used:</b> <jsp:getProperty name="helper" property="inboundTransferred" />/<jsp:getProperty name="helper" property="outboundTransferred" /><br /> + <hr /> + + <jsp:getProperty name="helper" property="destinations" /> + + <u><b>Tunnels in/out</b></u><br /> + <b>Exploratory:</b> <jsp:getProperty name="helper" property="inboundTunnels" />/<jsp:getProperty name="helper" property="outboundTunnels" /><br /> + <b>Client:</b> <jsp:getProperty name="helper" property="inboundClientTunnels" />/<jsp:getProperty name="helper" property="outboundClientTunnels" /><br /> + <b>Participating:</b> <jsp:getProperty name="helper" property="participatingTunnels" /><br /> + <hr /> + + <u><b>Congestion</b></u><br /> + <b>Job lag:</b> <jsp:getProperty name="helper" property="jobLag" /><br /> + <b>Message delay:</b> <jsp:getProperty name="helper" property="messageDelay" /><br /> + <b>Tunnel lag:</b> <jsp:getProperty name="helper" property="tunnelLag" /><br /> + <b>Handle backlog:</b> <jsp:getProperty name="helper" property="inboundBacklog" /><br /> + <b><jsp:getProperty name="helper" property="tunnelStatus" /></b><br /> + diff --git a/apps/sam/java/build.xml b/apps/sam/java/build.xml index bb692f2db3c3d0c8ef0b5cd8d7bad0fe95ac8b89..78f9cdfb0a26af4c91cb8a504b8f1b50d5b0e1f8 100644 --- a/apps/sam/java/build.xml +++ b/apps/sam/java/build.xml @@ -21,6 +21,7 @@ </classpath> </depend> </target> + <property name="javac.compilerargs" value="" /> <target name="compile" depends="depend"> <mkdir dir="./build" /> <mkdir dir="./build/obj" /> @@ -28,14 +29,18 @@ srcdir="./src" debug="true" deprecation="on" source="1.5" target="1.5" destdir="./build/obj" - classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" /> + classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" > + <compilerarg line="${javac.compilerargs}" /> + </javac> </target> <target name="compileTest" depends="compile"> <javac srcdir="./test" debug="true" deprecation="on" source="1.5" target="1.5" destdir="./build/obj" - classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" /> + classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" > + <compilerarg line="${javac.compilerargs}" /> + </javac> </target> <target name="jar" depends="compile"> <jar destfile="./build/sam.jar" basedir="./build/obj" includes="**/*.class"> diff --git a/apps/streaming/java/build.xml b/apps/streaming/java/build.xml index a32ca077c336db1dc1175ef5901b8adebc7fad9b..7740a60226169b9facff377f6d00c040373004c2 100644 --- a/apps/streaming/java/build.xml +++ b/apps/streaming/java/build.xml @@ -21,6 +21,7 @@ </classpath> </depend> </target> + <property name="javac.compilerargs" value="" /> <target name="compile" depends="depend"> <mkdir dir="./build" /> <mkdir dir="./build/obj" /> @@ -28,14 +29,18 @@ srcdir="./src" debug="true" deprecation="on" source="1.5" target="1.5" destdir="./build/obj" - classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" /> + classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" > + <compilerarg line="${javac.compilerargs}" /> + </javac> </target> <target name="compileTest" depends="compile"> <javac srcdir="./test" debug="true" deprecation="on" source="1.5" target="1.5" destdir="./build/obj" - classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" /> + classpath="../../../core/java/build/i2p.jar:../../ministreaming/java/build/mstreaming.jar" > + <compilerarg line="${javac.compilerargs}" /> + </javac> </target> <target name="jar" depends="builddep, compile"> <jar destfile="./build/streaming.jar" basedir="./build/obj" includes="**/*.class" /> diff --git a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionHandler.java b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionHandler.java index 2d198ad66e75bc4af62fa1aa24fe7b2ab293dd60..f4b00c1b567592d816a449eb1dc0c58dd5771fcd 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionHandler.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionHandler.java @@ -2,8 +2,6 @@ package net.i2p.client.streaming; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import java.util.ArrayList; -import java.util.List; import net.i2p.I2PAppContext; import net.i2p.util.Log; @@ -126,7 +124,7 @@ class ConnectionHandler { if (timeoutMs <= 0) { try { syn = _synQueue.take(); // waits forever - } catch (InterruptedException ie) { break;} + } catch (InterruptedException ie) { } // { break;} } else { long remaining = expiration - _context.clock().now(); // (dont think this applies anymore for LinkedBlockingQueue) diff --git a/apps/streaming/java/src/net/i2p/client/streaming/PacketLocal.java b/apps/streaming/java/src/net/i2p/client/streaming/PacketLocal.java index 197b9275412b1f8fa538c78e1a518b3b421d0de5..827be5b04fb6e035629c582a533716eae2eea625 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/PacketLocal.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/PacketLocal.java @@ -213,7 +213,7 @@ public class PacketLocal extends Packet implements MessageOutputStream.WriteStat timeRemaining = 10*1000; wait(timeRemaining); } - } catch (InterruptedException ie) { break; } + } catch (InterruptedException ie) { }//{ break; } } if (!writeSuccessful()) releasePayload(); diff --git a/apps/streaming/java/src/net/i2p/client/streaming/SchedulerChooser.java b/apps/streaming/java/src/net/i2p/client/streaming/SchedulerChooser.java index 3ed8327ddfb534bfd722abd325a6a4919602ab10..a2aacf82e2c0ea56daee7d2e3a9a0124e5406ccc 100644 --- a/apps/streaming/java/src/net/i2p/client/streaming/SchedulerChooser.java +++ b/apps/streaming/java/src/net/i2p/client/streaming/SchedulerChooser.java @@ -55,7 +55,7 @@ class SchedulerChooser { } public void eventOccurred(Connection con) { - _log.log(Log.CRIT, "Yell at jrandom: Event occurred on " + con, new Exception("source")); + _log.log(Log.ERROR, "Yell at jrandom: Event occurred on " + con, new Exception("source")); } public boolean accept(Connection con) { return true; } }; diff --git a/apps/susidns/src/build.xml b/apps/susidns/src/build.xml index d3f5f1662c72284c6677379b447a60970f436753..be34b4879e3fa706f1325a0e2d4d670b89b109bf 100644 --- a/apps/susidns/src/build.xml +++ b/apps/susidns/src/build.xml @@ -22,10 +22,13 @@ <pathelement location="${lib}/ant.jar" /> <pathelement location="../../../core/java/build/i2p.jar" /> </path> + <property name="javac.compilerargs" value="" /> <target name="compile"> <mkdir dir="${bin}" /> <javac debug="true" deprecation="on" source="1.5" target="1.5" - classpathref="cp" destdir="${bin}" srcdir="${src}" includes="**/*.java" /> + classpathref="cp" destdir="${bin}" srcdir="${src}" includes="**/*.java" > + <compilerarg line="${javac.compilerargs}" /> + </javac> </target> <target name="precompilejsp" unless="precompilejsp.uptodate"> <delete file="WEB-INF/web-fragment.xml" /> @@ -45,6 +48,7 @@ </java> <javac debug="true" deprecation="on" source="1.5" target="1.5" destdir="${bin}" srcdir="./WEB-INF/classes" includes="**/*.java" classpathref="cp"> + <compilerarg line="${javac.compilerargs}" /> </javac> <copy file="WEB-INF/web-template.xml" tofile="WEB-INF/web-out.xml" /> <loadfile property="jspc.web.fragment" srcfile="WEB-INF/web-fragment.xml" /> diff --git a/apps/susimail/build.xml b/apps/susimail/build.xml index abf2a88cf71c2829a9ca9beeada5ad658f02e7f7..886f9471f6425982bb3f71a2747118fa02c0ac31 100644 --- a/apps/susimail/build.xml +++ b/apps/susimail/build.xml @@ -5,11 +5,13 @@ <target name="builddep"> <ant dir="../jetty/" target="build" /> </target> + <property name="javac.compilerargs" value="" /> <target name="compile"> <javac srcdir="./src/src" debug="true" deprecation="off" source="1.5" target="1.5" destdir="./src/WEB-INF/classes"> + <compilerarg line="${javac.compilerargs}" /> <classpath> <pathelement location="../jetty/jettylib/javax.servlet.jar" /> <pathelement location="../jetty/jettylib/org.mortbay.jetty.jar" /> diff --git a/apps/systray/java/build.xml b/apps/systray/java/build.xml index 19db56d5ca76c2b7424ec3ef21a232dae0545005..1597f20b359a24ec9d940c847cd2057b1fef1df3 100644 --- a/apps/systray/java/build.xml +++ b/apps/systray/java/build.xml @@ -5,6 +5,7 @@ <target name="builddep"> <ant dir="../../../core/java/" target="build" /> </target> + <property name="javac.compilerargs" value="" /> <target name="compile"> <mkdir dir="./build" /> <mkdir dir="./build/obj" /> @@ -16,7 +17,9 @@ target="1.5" destdir="./build/obj" includes="**/*.java" - classpath="./lib/systray4j.jar:../../../core/java/build/i2p.jar" /> + classpath="./lib/systray4j.jar:../../../core/java/build/i2p.jar" > + <compilerarg line="${javac.compilerargs}" /> + </javac> </target> <target name="jar" depends="compile" unless="jar.uptodate"> <mkdir dir="./build/jar_temp" /> diff --git a/build.xml b/build.xml index 3a30ff8e7f8d5684907200a377179c624d863152..453b0d44c3c415927179845757d4a3269f2e131d 100644 --- a/build.xml +++ b/build.xml @@ -1,6 +1,13 @@ <?xml version="1.0" encoding="ISO-8859-1"?> <project basedir="." default="all" name="i2p"> + <!-- Things you might want to change --> + <!-- This keeps gcj a lot quieter --> + <!-- + <property name="javac.compilerargs" value="-warn:-unchecked,raw,unused,serial" /> + --> + + <!-- You probably don't want to change anything from here down --> <target name="all" > <echo message="Useful targets: " /> <echo message=" pkg: distclean then package everything up (installer, clean tarball, update tarball)" /> @@ -9,6 +16,7 @@ <echo message=" tarball: tar the full install into i2p.tar.bz2 (extracts to build a new clean install)" /> <echo message=" updater: tar the built i2p specific files into an i2pupdate.zip (extracts safely over existing installs)" /> <echo message=" updaterWithJetty: tar the built i2p specific files and jetty into an i2pupdate.zip (extracts safely over existing installs)" /> + <echo message=" updaterWithJettyFixes: updater including local jetty patches" /> <echo message=" updaterSmall: updater with the essentials only - no SAM, i2psnark, SusiMail, SusiDNS, news.xml, or history.txt" /> <echo message=" updaterRouter: updater with the i2p.jar and router.jar only" /> <echo message=" distclean: clean up all derived files" /> @@ -189,7 +197,7 @@ <fileset dir="." includes="**/*.java~" /> </delete> </target> - <target name="pkg" depends="distclean, updater, tarball, installer" /> + <target name="pkg" depends="distclean, updaterWithJettyFixes, tarball, installer" /> <target name="pkgclean"> <delete dir="pkg-temp" /> <delete> @@ -321,6 +329,9 @@ <target name="updaterWithJetty" depends="prepjupdate"> <zip destfile="i2pupdate.zip" basedir="pkg-temp" /> </target> + <target name="updaterWithJettyFixes" depends="prepjupdatefixes"> + <zip destfile="i2pupdate.zip" basedir="pkg-temp" /> + </target> <target name="updaterSmall" depends="prepupdateSmall"> <zip destfile="i2pupdate.zip" basedir="pkg-temp" /> </target> @@ -379,6 +390,9 @@ <copy file="build/javax.servlet.jar" todir="pkg-temp/lib/" /> <copy file="build/org.mortbay.jetty.jar" todir="pkg-temp/lib/" /> </target> + <target name="prepjupdatefixes" depends="prepupdate, buildWEB"> + <copy file="build/org.mortbay.jetty.jar" todir="pkg-temp/lib/" /> + </target> <target name="installer" depends="preppkg"> <taskdef name="izpack" classpath="${basedir}/installer/lib/izpack/standalone-compiler.jar" classname="com.izforge.izpack.ant.IzPackTask" /> <jar destfile="./pkg-temp/lib/copy.jar" basedir="./core/java/build/obj" includes="net/i2p/util/Copy.class net/i2p/util/FileUtil.class"> diff --git a/core/java/build.xml b/core/java/build.xml index 28adbf9df288733c0aabd7aae49c4a432cea664d..a52dcb63542d68e54a4159a24022a53761bc9854 100644 --- a/core/java/build.xml +++ b/core/java/build.xml @@ -15,15 +15,21 @@ destdir="./build/obj" > </depend> </target> + <!-- only used if not set by a higher build.xml --> + <property name="javac.compilerargs" value="" /> <target name="compile" depends="depend"> <mkdir dir="./build" /> <mkdir dir="./build/obj" /> - <javac srcdir="./src" debug="true" source="1.5" target="1.5" deprecation="on" destdir="./build/obj" /> + <javac srcdir="./src" debug="true" source="1.5" target="1.5" deprecation="on" destdir="./build/obj" > + <compilerarg line="${javac.compilerargs}" /> + </javac> </target> <target name="compileTest"> <mkdir dir="./build" /> <mkdir dir="./build/obj" /> - <javac srcdir="./src:./test" debug="true" source="1.5" target="1.5" deprecation="on" destdir="./build/obj" /> + <javac srcdir="./src:./test" debug="true" source="1.5" target="1.5" deprecation="on" destdir="./build/obj" > + <compilerarg line="${javac.compilerargs}" /> + </javac> </target> <target name="jar" depends="compile"> <jar destfile="./build/i2p.jar" basedir="./build/obj" includes="**/*.class" /> diff --git a/core/java/src/net/i2p/CoreVersion.java b/core/java/src/net/i2p/CoreVersion.java index 6c924fe1092d4c0e2e03679c59b8ebd7fad3a00e..685abc2f059542efc30e4b29739c6709410d32a2 100644 --- a/core/java/src/net/i2p/CoreVersion.java +++ b/core/java/src/net/i2p/CoreVersion.java @@ -15,7 +15,7 @@ package net.i2p; */ public class CoreVersion { public final static String ID = "$Revision: 1.72 $ $Date: 2008-08-24 12:00:00 $"; - public final static String VERSION = "0.7.1"; + public final static String VERSION = "0.7.2"; public static void main(String args[]) { System.out.println("I2P Core version: " + VERSION); diff --git a/core/java/src/net/i2p/client/I2PSessionImpl.java b/core/java/src/net/i2p/client/I2PSessionImpl.java index 9e42eef5fa3e983f083c76c0b850c9da444e9b2f..a5d8ed94de3003a0e21717c41eeb0aaac2a5160b 100644 --- a/core/java/src/net/i2p/client/I2PSessionImpl.java +++ b/core/java/src/net/i2p/client/I2PSessionImpl.java @@ -16,7 +16,6 @@ import java.net.Socket; import java.net.UnknownHostException; import java.util.concurrent.ConcurrentHashMap; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -90,7 +89,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa protected I2PAppContext _context; /** monitor for waiting until a lease set has been granted */ - private Object _leaseSetWait = new Object(); + private final Object _leaseSetWait = new Object(); /** whether the session connection has already been closed (or not yet opened) */ protected boolean _closed; @@ -101,7 +100,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa /** have we received the current date from the router yet? */ private boolean _dateReceived; /** lock that we wait upon, that the SetDateMessageHandler notifies */ - private Object _dateReceivedLock = new Object(); + private final Object _dateReceivedLock = new Object(); /** * thread that we tell when new messages are available who then tells us @@ -253,6 +252,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa try { if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "connect begin to " + _hostname + ":" + _portNum); _socket = new Socket(_hostname, _portNum); + // _socket.setSoTimeout(1000000); // Uhmmm we could really-really use a real timeout, and handle it. _out = _socket.getOutputStream(); synchronized (_out) { _out.write(I2PClient.PROTOCOL_BYTE); diff --git a/core/java/src/net/i2p/client/I2PSessionMuxedImpl.java b/core/java/src/net/i2p/client/I2PSessionMuxedImpl.java index a3e5e57a7f870087cff8648ca15e39bce4d7d3d9..eda48e75444cb6b1c190825a877642d6f0f58cf0 100644 --- a/core/java/src/net/i2p/client/I2PSessionMuxedImpl.java +++ b/core/java/src/net/i2p/client/I2PSessionMuxedImpl.java @@ -4,18 +4,16 @@ package net.i2p.client; * public domain */ -import java.io.IOException; import java.io.InputStream; import java.util.concurrent.LinkedBlockingQueue; -import java.util.HashSet; import java.util.Properties; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; import net.i2p.I2PAppContext; import net.i2p.data.DataHelper; import net.i2p.data.Destination; import net.i2p.data.SessionKey; -import net.i2p.data.SessionTag; import net.i2p.data.i2cp.MessagePayloadMessage; import net.i2p.util.Log; import net.i2p.util.SimpleScheduler; @@ -97,6 +95,7 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession { * 255 disallowed * @param port 1-65535 or PORT_ANY for all */ + @Override public void addSessionListener(I2PSessionListener lsnr, int proto, int port) { _demultiplexer.addListener(lsnr, proto, port); } @@ -107,11 +106,13 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession { * @param proto 1-254 or 0 for all; 255 disallowed * @param port 1-65535 or 0 for all */ + @Override public void addMuxedSessionListener(I2PSessionMuxedListener l, int proto, int port) { _demultiplexer.addMuxedListener(l, proto, port); } /** removes the specified listener (only) */ + @Override public void removeListener(int proto, int port) { _demultiplexer.removeListener(proto, port); } @@ -149,6 +150,7 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession { * @param fromPort 1-65535 or 0 for unset * @param toPort 1-65535 or 0 for unset */ + @Override public boolean sendMessage(Destination dest, byte[] payload, int offset, int size, SessionKey keyUsed, Set tagsSent, long expires, int proto, int fromPort, int toPort) @@ -198,24 +200,36 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession { protected class MuxedAvailabilityNotifier extends AvailabilityNotifier { private LinkedBlockingQueue<MsgData> _msgs; - private boolean _alive; + private AtomicBoolean _alive = new AtomicBoolean(false); private static final int POISON_SIZE = -99999; public MuxedAvailabilityNotifier() { _msgs = new LinkedBlockingQueue(); } - - public void stopNotifying() { - _msgs.clear(); - if (_alive) { - _alive = false; - try { - _msgs.put(new MsgData(0, POISON_SIZE, 0, 0, 0)); - } catch (InterruptedException ie) {} + + @Override + public void stopNotifying() { + boolean again = true; + _msgs.clear(); + // Thread.yield(); + if (_alive.get()) { + // System.out.println("I2PSessionMuxedImpl.stopNotifying()"); + while(again) { + _msgs.clear(); + try { + _msgs.put(new MsgData(0, POISON_SIZE, 0, 0, 0)); + again = false; + // System.out.println("I2PSessionMuxedImpl.stopNotifying() success."); + } catch (InterruptedException ie) { + continue; + } + } } + _alive.set(false); } /** unused */ + @Override public void available(long msgId, int size) { throw new IllegalArgumentException("no"); } public void available(long msgId, int size, int proto, int fromPort, int toPort) { @@ -224,20 +238,24 @@ class I2PSessionMuxedImpl extends I2PSessionImpl2 implements I2PSession { } catch (InterruptedException ie) {} } + @Override public void run() { - _alive = true; - while (true) { - MsgData msg; + MsgData msg; + _alive.set(true); + while (_alive.get()) { try { msg = _msgs.take(); } catch (InterruptedException ie) { + _log.debug("I2PSessionMuxedImpl.run() InterruptedException " + String.valueOf(_msgs.size()) + " Messages, Alive " + _alive.toString()); continue; } - if (msg.size == POISON_SIZE) + if (msg.size == POISON_SIZE) { + // System.out.println("I2PSessionMuxedImpl.run() POISONED"); break; + } try { - _demultiplexer.messageAvailable(I2PSessionMuxedImpl.this, msg.id, - msg.size, msg.proto, msg.fromPort, msg.toPort); + _demultiplexer.messageAvailable(I2PSessionMuxedImpl.this, + msg.id, msg.size, msg.proto, msg.fromPort, msg.toPort); } catch (Exception e) { _log.error("Error notifying app of message availability"); } diff --git a/core/java/src/net/i2p/data/LeaseSet.java b/core/java/src/net/i2p/data/LeaseSet.java index 8a05dd9569bb744599f7d0e8dc1e51d8e6a786f4..66d10da94471cf3bbcea595eb8e6246fc23be417 100644 --- a/core/java/src/net/i2p/data/LeaseSet.java +++ b/core/java/src/net/i2p/data/LeaseSet.java @@ -67,7 +67,7 @@ public class LeaseSet extends DataStructureImpl { private boolean _checked; /** This seems like plenty */ - private final static int MAX_LEASES = 6; + public final static int MAX_LEASES = 6; public LeaseSet() { setDestination(null); diff --git a/core/java/src/net/i2p/util/EepGet.java b/core/java/src/net/i2p/util/EepGet.java index 5f0e8d5e9fcdfcf9ed1470c3d477324ef6cc1b8b..c3c18866a7d251cde86d187735d02fa4cb80c668 100644 --- a/core/java/src/net/i2p/util/EepGet.java +++ b/core/java/src/net/i2p/util/EepGet.java @@ -159,6 +159,9 @@ public class EepGet { markSize = Integer.parseInt(args[i+1]); lineLen = Integer.parseInt(args[i+2]); i += 2; + } else if (args[i].startsWith("-")) { + usage(); + return; } else { url = args[i]; } diff --git a/history.txt b/history.txt index ff522acbd5807edfb0cd6a8153a61ac4a86c9f6f..cfc2af8535db50d12921eb81358c93d7736c5c8c 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,68 @@ +2009-04-27 sponge + * more BOB fixes, complete with warnings when things go wrong, and + success messages when things turn around and go right. Terminates + early so that applications wait no more than 10 seconds or so. + * Reversed a few earlier patches that caused some odd behavior. + * Changed some core println()'s to debugging messages. + +2009-04-27 zzz + * Build files: + - New updaterWithJettyFixes target, build it for pkg + - Pass compiler args down from top build.xml + * GarlicMessageBuilder: Reduce bundled tags to 40 (was 100) + * i2psnark: Add Postman2 tracker + * I2PTunnel: Allow spaces in dest and proxy lists + * NetDb: + - Adjust RouterInfo expiration down to control memory usage + - Display LeaseSets and RouterInfos on separate console pages + * NTCP: + - Correct the meanings of the i2np.ntcp.autoip and i2np.ntcp.autoport + advanced config. If you have one of these set but not the other, you + will have to adjust your configuration on config.jsp. + * RouterConsole: iframe tweaks + * StatisticsManager: Cleanup + * Streaming: Don't let jrandom yell so loud + +2009-04-25 sponge + * I2PSessionMuxedImpl atomic fixes + * BOB fixes. This should be the final bug wack. Good Luck to everybody! + +2009-04-23 zzz + * Blocklist: cleanup + * eepget: handle -h, --help, bad options, etc. + (http://forum.i2p/viewtopic.php?p=16261#16261) + * Fragmenter: don't re-throw the corrupt fragment IllegalStateException, + to limit the damage - root cause still not found + * i2psnark: (http://forum.i2p/viewtopic.php?t=3317) + - Change file limit to 512 (was 256) + - Change size limit to 10GB (was 5GB) + - Change request size to 16KB (was 32KB) + - Change pipeline to 5 (was 3) + * logs.jsp: Move version info to the top + * Jetty: Fix temp dir name handling on windows, which was + causing susidns not to start + (http://forum.i2p/viewtopic.php?t=3364) + * NTCP: Prevent IllegalStateException + * PeerProfile: + - Replace a hot lock with concurrent RW lock + - Rewrite ugly IP Restriction code + - Also use transport IP in restriction code + * RouterConsole: Make summary bar a refreshing iframe + * Transport: Start the previously unused CleanupUnreachable + +2009-04-21 sponge + * Code janitor work, basic corrections involving @Override, and + appling final where it is important. Also fixed some equals methods + and commented places that need fixing. + +2009-04-18 Complication + * Fix typo in "news.xml", no build number increase. + +* 2009-04-18 0.7.2 released + +2009-04-18 Complication + * Update versions, package release + 2009-04-17 sponge * fixed setIP, just be sure to distclean before building :-) * more lint taken care of as well. diff --git a/initialNews.xml b/initialNews.xml index 0306dcd7b25a9b1c8a0e45c4f90ebb43c28d46ab..ed08caba2dec5edbebfea6d4e5b8c269b4a8d78e 100644 --- a/initialNews.xml +++ b/initialNews.xml @@ -1,5 +1,5 @@ -<i2p.news date="$Date: 2009-03-29 00:00:00 $"> - <i2p.release version="0.7.1" date="2009/03/29" minVersion="0.6" +<i2p.news date="$Date: 2009-04-18 00:00:00 $"> + <i2p.release version="0.7.2" date="2009/04/18" minVersion="0.6" /> <center><h2>Congratulations on getting I2P installed!</h2></center> <ul> diff --git a/installer/install.xml b/installer/install.xml index 125e92231c62cf72db19b979c50c5abc34d30fbf..74cd95cb4dc8a6dcd7998cd7bf18f8060de99e4a 100644 --- a/installer/install.xml +++ b/installer/install.xml @@ -4,7 +4,7 @@ <info> <appname>i2p</appname> - <appversion>0.7.1</appversion> + <appversion>0.7.2</appversion> <authors> <author name="I2P" email="http://forum.i2p2.de/"/> </authors> diff --git a/installer/lib/launch4j/build.xml b/installer/lib/launch4j/build.xml index 42c77a225f04a9365f2eaba3d5e71851083f5bc0..767e7c59271a9dfac33f24e3aef5fe6620ea52b2 100644 --- a/installer/lib/launch4j/build.xml +++ b/installer/lib/launch4j/build.xml @@ -7,6 +7,7 @@ <property name="dist" location="${user.home}/dist/${ant.project.name}" /> <property name="jar" location="./${ant.project.name}.jar" /> <property name="launch4j.dir" location="." /> + <property name="javac.compilerargs" value="" /> <path id="dist.classpath"> <pathelement path="${build}" /> @@ -23,6 +24,8 @@ <target name="compile" depends="init" description="compile the source"> <javac srcdir="${src}" destdir="${build}" classpathref="dist.classpath" source="1.4" debug="on" /> + <compilerarg line="${javac.compilerargs}" /> + </javac> <copy todir="${build}/images"> <fileset dir="${src}/images"> <include name="**/*" /> diff --git a/installer/resources/jetty.xml b/installer/resources/jetty.xml index b55831e7440595b1e8c2479fc844232e0af33f96..a9c04d9644858d7c28618488851a8d479583034d 100644 --- a/installer/resources/jetty.xml +++ b/installer/resources/jetty.xml @@ -1,6 +1,32 @@ <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure 1.2//EN" "http://jetty.mortbay.org/configure_1_2.dtd"> +<!-- ========================================================================= --> +<!-- This file configures the Jetty server. --> +<!-- All changes require a restart of I2P. --> +<!-- --> +<!-- Commonly changed settings: --> +<!-- * host: Change 127.0.0.1 to 0.0.0.0 in the addListener section --> +<!-- to access the server directly (bypassing i2p) --> +<!-- from other computers. The included version of Jetty has --> +<!-- been patched to allow IPv6 addresses as well, --> +<!-- enclosed in brackets e.g. [::1] --> +<!-- * port: Default 7658 in the addListener section --> +<!-- * threads: Raise MaxThreads in the addListener section --> +<!-- if you have a high-traffic site and get a lot of warnings. --> +<!-- * Uncomment the addWebApplications section to use to enable --> +<!-- war files placed in the webapps/ dir. --> +<!-- --> +<!-- I2P uses Jetty 5.1.12. We have no plans to upgrade to Jetty 6, due to --> +<!-- the significant changes in the API. If you need web server features not --> +<!-- found in Jetty 5, you may install and run Jetty 6 in a different JVM, --> +<!-- or run any other web server such as Apache. If you do run another --> +<!-- web server instead, be sure and disable the Jetty 5 server for your --> +<!-- eepsite on http://127.0.0.1/configclients.jsp . --> +<!-- --> +<!-- Jetty errors and warnings will appear in wrapper.log, check there --> +<!-- to diagnose problems. --> +<!-- ========================================================================= --> <!-- =============================================================== --> <!-- Configure the Jetty Server --> diff --git a/news.xml b/news.xml index b85e0f130898fcd25ef3c14e8febbf410687db6b..e5bb34a21a40a775cdb0e8fbdab146c5927a6037 100644 --- a/news.xml +++ b/news.xml @@ -1,5 +1,5 @@ -<i2p.news date="$Date: 2009-03-29 00:00:00 $"> - <i2p.release version="0.7.1" date="2009/03/29" minVersion="0.6" +<i2p.news date="$Date: 2009-04-18 00:00:00 $"> + <i2p.release version="0.7.2" date="2009/04/18" minVersion="0.6" anonurl="http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/i2p/i2pupdate.sud" publicurl="http://dev.i2p.net/i2p/i2pupdate.sud" anonannouncement="http://i2p/NF2RLVUxVulR3IqK0sGJR0dHQcGXAzwa6rEO4WAWYXOHw-DoZhKnlbf1nzHXwMEJoex5nFTyiNMqxJMWlY54cvU~UenZdkyQQeUSBZXyuSweflUXFqKN-y8xIoK2w9Ylq1k8IcrAFDsITyOzjUKoOPfVq34rKNDo7fYyis4kT5bAHy~2N1EVMs34pi2RFabATIOBk38Qhab57Umpa6yEoE~rbyR~suDRvD7gjBvBiIKFqhFueXsR2uSrPB-yzwAGofTXuklofK3DdKspciclTVzqbDjsk5UXfu2nTrC1agkhLyqlOfjhyqC~t1IXm-Vs2o7911k7KKLGjB4lmH508YJ7G9fLAUyjuB-wwwhejoWqvg7oWvqo4oIok8LG6ECR71C3dzCvIjY2QcrhoaazA9G4zcGMm6NKND-H4XY6tUWhpB~5GefB3YczOqMbHq4wi0O9MzBFrOJEOs3X4hwboKWANf7DT5PZKJZ5KorQPsYRSq0E3wSOsFCSsdVCKUGsAAAA/pipermail/i2p/2005-September/000878.html" @@ -11,25 +11,25 @@ publiclogs="http://www.i2p.net/meeting141" /> <p> • -2009-03-29: <b>0.7.1 <a href="http://www.i2p2.i2p/release-0.7.1.html">Released</a></b> +2009-04-18: <b>0.7.2 <a href="http://www.i2p2.i2p/release-0.7.2.html">Released</a></b> </p><p> -The 0.7.1 release optimizes I2P towards better performance -and introduces new features. +The 0.7.2 release fixes multiple bugs and potential problems +in I2P, while preparing ground for new functionality. </p><p> -Multiple bugs are fixed, replacements to the SimpleTimer class -should waste less time on object locking. Some old components -are dropped and several classes refactored to avoid repeating code. +Threading issues with the SimpleTimer class should no longer occur, +the NTCP transport should no longer encounter null pointer exceptions, +and "abandoned" tunnels should finish operation correctly. </p><p> -Support for encrypted LeaseSets (for creation of links over I2P -which an adversary cannot obstruct by attacking its gateways) -becomes more complete. New tunnel types like IRC server tunnels -and new options like delayed start and idling of tunnels -also gain support, along with improved usability of the I2P -Socks proxy mechanism. +Support is added for accessing the Router Console over IPv6, +a new message type enables I2CP applications to query +the router's bandwidth limits, an experimental desktop interface +for managing the router is included for the first time +(but not enabled automatically yet) and participation of a single peer +in too many tunnels is prevented to improve reliability and safety. </p><p> -Work continues on streamlining and expanding the Router Console, -on the BOB protocol, on I2P ports for Debian and Slackware Linux, -on the I2PSnark client, on TCP connection properties -and multiple other fronts. Updating is highly recommended. +Besides other maintenance work, several old statistics calculators +are dropped to make router profiles smaller and quicker, while +new build scripts are supplied for I2P's big integer math library. +Updating is highly recommended. </p> </i2p.news> diff --git a/router/java/build.xml b/router/java/build.xml index 95878e468fa88434d47c13d64903a8042ede1020..70f83fbd7027df90779b65bacb65554d1467cc9f 100644 --- a/router/java/build.xml +++ b/router/java/build.xml @@ -22,15 +22,21 @@ </classpath> </depend> </target> + <!-- only used if not set by a higher build.xml --> + <property name="javac.compilerargs" value="" /> <target name="compile" depends="depend"> <mkdir dir="./build" /> <mkdir dir="./build/obj" /> - <javac srcdir="./src" debug="true" source="1.5" target="1.5" deprecation="on" destdir="./build/obj" classpath="../../core/java/build/i2p.jar" /> + <javac srcdir="./src" debug="true" source="1.5" target="1.5" deprecation="on" destdir="./build/obj" classpath="../../core/java/build/i2p.jar" > + <compilerarg line="${javac.compilerargs}" /> + </javac> </target> <target name="compileTest" depends="builddeptest"> <mkdir dir="./build" /> <mkdir dir="./build/obj" /> - <javac srcdir="./src:./test" debug="true" source="1.5" target="1.5" deprecation="on" destdir="./build/obj" classpath="../../core/java/build/i2ptest.jar" /> + <javac srcdir="./src:./test" debug="true" source="1.5" target="1.5" deprecation="on" destdir="./build/obj" classpath="../../core/java/build/i2ptest.jar" > + <compilerarg line="${javac.compilerargs}" /> + </javac> </target> <target name="jar" depends="compile"> <jar destfile="./build/router.jar" basedir="./build/obj" includes="**/*.class" /> diff --git a/router/java/src/net/i2p/data/i2np/DataMessage.java b/router/java/src/net/i2p/data/i2np/DataMessage.java index 7e839117fa040ddadb4aa0bb85d1f789f3134b20..8ba6b13460e579a88e5898e44859a49242574595 100644 --- a/router/java/src/net/i2p/data/i2np/DataMessage.java +++ b/router/java/src/net/i2p/data/i2np/DataMessage.java @@ -12,7 +12,7 @@ import java.io.IOException; import net.i2p.I2PAppContext; import net.i2p.data.DataHelper; -import net.i2p.util.Log; +// import net.i2p.util.Log; /** * Defines a message containing arbitrary bytes of data @@ -20,11 +20,11 @@ import net.i2p.util.Log; * @author jrandom */ public class DataMessage extends I2NPMessageImpl { - private final static Log _log = new Log(DataMessage.class); + // private final static Log _log = new Log(DataMessage.class); public final static int MESSAGE_TYPE = 20; private byte _data[]; - private static final int MAX_SIZE = 64*1024; + // private static final int MAX_SIZE = 64*1024; // LINT -- field hides another field, and not used public DataMessage(I2PAppContext context) { super(context); @@ -81,6 +81,7 @@ public class DataMessage extends I2NPMessageImpl { return curIndex; } + @Override protected void written() { super.written(); _data = null; @@ -88,10 +89,12 @@ public class DataMessage extends I2NPMessageImpl { public int getType() { return MESSAGE_TYPE; } + @Override public int hashCode() { return DataHelper.hashCode(getData()); } + @Override public boolean equals(Object object) { if ( (object != null) && (object instanceof DataMessage) ) { DataMessage msg = (DataMessage)object; @@ -101,6 +104,7 @@ public class DataMessage extends I2NPMessageImpl { } } + @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("[DataMessage: "); diff --git a/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java b/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java index 4a6da92e3f148ad1342cca30131e6fed4a8e6b28..79dec2ee9b41d0ba257e3d2fbf0b9d2e934fdfee 100644 --- a/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java +++ b/router/java/src/net/i2p/data/i2np/DatabaseLookupMessage.java @@ -215,6 +215,7 @@ public class DatabaseLookupMessage extends I2NPMessageImpl { public int getType() { return MESSAGE_TYPE; } + @Override public int hashCode() { return DataHelper.hashCode(getSearchKey()) + DataHelper.hashCode(getFrom()) + @@ -222,6 +223,7 @@ public class DatabaseLookupMessage extends I2NPMessageImpl { DataHelper.hashCode(_dontIncludePeers); } + @Override public boolean equals(Object object) { if ( (object != null) && (object instanceof DatabaseLookupMessage) ) { DatabaseLookupMessage msg = (DatabaseLookupMessage)object; @@ -234,6 +236,7 @@ public class DatabaseLookupMessage extends I2NPMessageImpl { } } + @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("[DatabaseLookupMessage: "); diff --git a/router/java/src/net/i2p/data/i2np/DatabaseSearchReplyMessage.java b/router/java/src/net/i2p/data/i2np/DatabaseSearchReplyMessage.java index 2f1bc87e708f9253a97b0926bbcedbaeae490652..c8dc9aa901bc651814ce1124e2318a136e8cb5cf 100644 --- a/router/java/src/net/i2p/data/i2np/DatabaseSearchReplyMessage.java +++ b/router/java/src/net/i2p/data/i2np/DatabaseSearchReplyMessage.java @@ -110,6 +110,7 @@ public class DatabaseSearchReplyMessage extends I2NPMessageImpl { public int getType() { return MESSAGE_TYPE; } + @Override public boolean equals(Object object) { if ( (object != null) && (object instanceof DatabaseSearchReplyMessage) ) { DatabaseSearchReplyMessage msg = (DatabaseSearchReplyMessage)object; @@ -121,12 +122,14 @@ public class DatabaseSearchReplyMessage extends I2NPMessageImpl { } } + @Override public int hashCode() { return DataHelper.hashCode(getSearchKey()) + DataHelper.hashCode(getFromHash()) + DataHelper.hashCode(_peerHashes); } + @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("[DatabaseSearchReplyMessage: "); diff --git a/router/java/src/net/i2p/data/i2np/DatabaseStoreMessage.java b/router/java/src/net/i2p/data/i2np/DatabaseStoreMessage.java index cb838daca3d6898ecdaa34fd6ea6e56c37059442..04ef417d3adfc776afcd465daa0f10452b83d378 100644 --- a/router/java/src/net/i2p/data/i2np/DatabaseStoreMessage.java +++ b/router/java/src/net/i2p/data/i2np/DatabaseStoreMessage.java @@ -231,6 +231,7 @@ public class DatabaseStoreMessage extends I2NPMessageImpl { public int getType() { return MESSAGE_TYPE; } + @Override public int hashCode() { return DataHelper.hashCode(getKey()) + DataHelper.hashCode(getLeaseSet()) + @@ -241,6 +242,7 @@ public class DatabaseStoreMessage extends I2NPMessageImpl { DataHelper.hashCode(getReplyGateway()); } + @Override public boolean equals(Object object) { if ( (object != null) && (object instanceof DatabaseStoreMessage) ) { DatabaseStoreMessage msg = (DatabaseStoreMessage)object; @@ -256,6 +258,7 @@ public class DatabaseStoreMessage extends I2NPMessageImpl { } } + @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("[DatabaseStoreMessage: "); diff --git a/router/java/src/net/i2p/data/i2np/DateMessage.java b/router/java/src/net/i2p/data/i2np/DateMessage.java index 554c31ef29c040cf604b2ebf02de3bb639a45ce3..b5388eda5ae8373d0e6c8607125511d4fd99b8f0 100644 --- a/router/java/src/net/i2p/data/i2np/DateMessage.java +++ b/router/java/src/net/i2p/data/i2np/DateMessage.java @@ -53,10 +53,12 @@ public class DateMessage extends I2NPMessageImpl { public int getType() { return MESSAGE_TYPE; } + @Override public int hashCode() { return (int)getNow(); } + @Override public boolean equals(Object object) { if ( (object != null) && (object instanceof DateMessage) ) { DateMessage msg = (DateMessage)object; @@ -66,6 +68,7 @@ public class DateMessage extends I2NPMessageImpl { } } + @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("[DateMessage: "); diff --git a/router/java/src/net/i2p/data/i2np/DeliveryInstructions.java b/router/java/src/net/i2p/data/i2np/DeliveryInstructions.java index 3e46fc8fe5b3fa95f6397fe019b416463d3b0c77..8ad3ddff28c269a48c07b605acf182d2c84d926f 100644 --- a/router/java/src/net/i2p/data/i2np/DeliveryInstructions.java +++ b/router/java/src/net/i2p/data/i2np/DeliveryInstructions.java @@ -350,6 +350,7 @@ public class DeliveryInstructions extends DataStructureImpl { + getAdditionalInfoSize(); } + @Override public boolean equals(Object obj) { if ( (obj == null) || !(obj instanceof DeliveryInstructions)) return false; @@ -364,6 +365,7 @@ public class DeliveryInstructions extends DataStructureImpl { DataHelper.eq(getTunnelId(), instr.getTunnelId()); } + @Override public int hashCode() { return (int)getDelaySeconds() + getDeliveryMode() + @@ -373,6 +375,7 @@ public class DeliveryInstructions extends DataStructureImpl { DataHelper.hashCode(getTunnelId()); } + @Override public String toString() { StringBuffer buf = new StringBuffer(128); buf.append("[DeliveryInstructions: "); diff --git a/router/java/src/net/i2p/data/i2np/DeliveryStatusMessage.java b/router/java/src/net/i2p/data/i2np/DeliveryStatusMessage.java index 9f1d61b45acef64443bb8a4695be1deb14470582..ff8ad12cbdc4da0f3997379a6b8e552d481d116e 100644 --- a/router/java/src/net/i2p/data/i2np/DeliveryStatusMessage.java +++ b/router/java/src/net/i2p/data/i2np/DeliveryStatusMessage.java @@ -64,10 +64,12 @@ public class DeliveryStatusMessage extends I2NPMessageImpl { public int getType() { return MESSAGE_TYPE; } + @Override public int hashCode() { return (int)getMessageId() + (int)getArrival(); } + @Override public boolean equals(Object object) { if ( (object != null) && (object instanceof DeliveryStatusMessage) ) { DeliveryStatusMessage msg = (DeliveryStatusMessage)object; @@ -78,6 +80,7 @@ public class DeliveryStatusMessage extends I2NPMessageImpl { } } + @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("[DeliveryStatusMessage: "); diff --git a/router/java/src/net/i2p/data/i2np/EndPointPrivateKey.java b/router/java/src/net/i2p/data/i2np/EndPointPrivateKey.java index 8f5763ae4819af4c7e30715ee8d001abd4d6cf67..4b3f919c84d9a8ed1839f9240ee315558f1162c7 100644 --- a/router/java/src/net/i2p/data/i2np/EndPointPrivateKey.java +++ b/router/java/src/net/i2p/data/i2np/EndPointPrivateKey.java @@ -44,17 +44,20 @@ public class EndPointPrivateKey extends DataStructureImpl { _key.writeBytes(out); } + @Override public boolean equals(Object obj) { if ( (obj == null) || !(obj instanceof EndPointPublicKey)) return false; return DataHelper.eq(getKey(), ((EndPointPublicKey)obj).getKey()); } + @Override public int hashCode() { if (_key == null) return 0; return getKey().hashCode(); } + @Override public String toString() { return "[EndPointPrivateKey: " + getKey() + "]"; } diff --git a/router/java/src/net/i2p/data/i2np/EndPointPublicKey.java b/router/java/src/net/i2p/data/i2np/EndPointPublicKey.java index 3920d0bda2ae6a3dedb5eb21efd2853dab6085a4..a366bf73bf83943741ae31dfd9c3b682f4c4df68 100644 --- a/router/java/src/net/i2p/data/i2np/EndPointPublicKey.java +++ b/router/java/src/net/i2p/data/i2np/EndPointPublicKey.java @@ -44,17 +44,20 @@ public class EndPointPublicKey extends DataStructureImpl { _key.writeBytes(out); } + @Override public boolean equals(Object obj) { if ( (obj == null) || !(obj instanceof EndPointPublicKey)) return false; return DataHelper.eq(getKey(), ((EndPointPublicKey)obj).getKey()); } + @Override public int hashCode() { if (_key == null) return 0; return getKey().hashCode(); } + @Override public String toString() { return "[EndPointPublicKey: " + getKey() + "]"; } diff --git a/router/java/src/net/i2p/data/i2np/GarlicClove.java b/router/java/src/net/i2p/data/i2np/GarlicClove.java index cb6808756fc3a5b4129ddd5aa7930d121cebf393..aa37994a07fe0539bbc26a6ad12b3beff4048a54 100644 --- a/router/java/src/net/i2p/data/i2np/GarlicClove.java +++ b/router/java/src/net/i2p/data/i2np/GarlicClove.java @@ -156,6 +156,7 @@ public class GarlicClove extends DataStructureImpl { _log.debug("Written cert: " + _certificate); } + @Override public byte[] toByteArray() { byte rv[] = new byte[estimateSize()]; int offset = 0; @@ -186,6 +187,7 @@ public class GarlicClove extends DataStructureImpl { + _certificate.size(); // certificate } + @Override public boolean equals(Object obj) { if ( (obj == null) || !(obj instanceof GarlicClove)) return false; @@ -197,6 +199,7 @@ public class GarlicClove extends DataStructureImpl { DataHelper.eq(getInstructions(), clove.getInstructions()); } + @Override public int hashCode() { return DataHelper.hashCode(getCertificate()) + (int)getCloveId() + @@ -205,6 +208,7 @@ public class GarlicClove extends DataStructureImpl { DataHelper.hashCode(getInstructions()); } + @Override public String toString() { StringBuffer buf = new StringBuffer(128); buf.append("[GarlicClove: "); diff --git a/router/java/src/net/i2p/data/i2np/GarlicMessage.java b/router/java/src/net/i2p/data/i2np/GarlicMessage.java index 5d76a2b224b3dbecdf5d885f0c263a6616ac9d04..357e7d2f5ee0603db1853e22155063ddf5b2c03c 100644 --- a/router/java/src/net/i2p/data/i2np/GarlicMessage.java +++ b/router/java/src/net/i2p/data/i2np/GarlicMessage.java @@ -67,15 +67,18 @@ public class GarlicMessage extends I2NPMessageImpl { public int getType() { return MESSAGE_TYPE; } + @Override public int hashCode() { return DataHelper.hashCode(getData()); } + @Override protected void written() { super.written(); _data = null; } + @Override public boolean equals(Object object) { if ( (object != null) && (object instanceof GarlicMessage) ) { GarlicMessage msg = (GarlicMessage)object; @@ -85,6 +88,7 @@ public class GarlicMessage extends I2NPMessageImpl { } } + @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("[GarlicMessage: "); diff --git a/router/java/src/net/i2p/data/i2np/I2NPMessageImpl.java b/router/java/src/net/i2p/data/i2np/I2NPMessageImpl.java index b745db9c0dd423f243c62ed63e98a93678e06739..e241ff1f4a349b294d8cdbad5ad94939faef186f 100644 --- a/router/java/src/net/i2p/data/i2np/I2NPMessageImpl.java +++ b/router/java/src/net/i2p/data/i2np/I2NPMessageImpl.java @@ -187,6 +187,7 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM return calculateWrittenLength()+5; } + @Override public byte[] toByteArray() { byte data[] = new byte[getMessageSize()]; int written = toByteArray(data); diff --git a/router/java/src/net/i2p/data/i2np/TunnelCreateMessage.java b/router/java/src/net/i2p/data/i2np/TunnelCreateMessage.java index f89e4b8989796b5443e48ee8a09f67197faf694d..b611f46728173e34c2b49f1b05972859b83ad2e1 100644 --- a/router/java/src/net/i2p/data/i2np/TunnelCreateMessage.java +++ b/router/java/src/net/i2p/data/i2np/TunnelCreateMessage.java @@ -232,6 +232,7 @@ public class TunnelCreateMessage extends I2NPMessageImpl { } + @Override public byte[] toByteArray() { byte rv[] = super.toByteArray(); if (rv == null) @@ -239,6 +240,7 @@ public class TunnelCreateMessage extends I2NPMessageImpl { return rv; } + @Override public int hashCode() { return DataHelper.hashCode(getNextRouter()) + DataHelper.hashCode(getNextTunnelId()) + @@ -246,6 +248,7 @@ public class TunnelCreateMessage extends I2NPMessageImpl { DataHelper.hashCode(getReplyTunnel()); } + @Override public boolean equals(Object object) { if ( (object != null) && (object instanceof TunnelCreateMessage) ) { TunnelCreateMessage msg = (TunnelCreateMessage)object; @@ -258,6 +261,7 @@ public class TunnelCreateMessage extends I2NPMessageImpl { } } + @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("[TunnelCreateMessage: "); diff --git a/router/java/src/net/i2p/data/i2np/TunnelCreateStatusMessage.java b/router/java/src/net/i2p/data/i2np/TunnelCreateStatusMessage.java index a5994f26de70308922e2faac825331862b479006..515436f5dd019e13fd606465ba9281812ef94983 100644 --- a/router/java/src/net/i2p/data/i2np/TunnelCreateStatusMessage.java +++ b/router/java/src/net/i2p/data/i2np/TunnelCreateStatusMessage.java @@ -87,12 +87,14 @@ public class TunnelCreateStatusMessage extends I2NPMessageImpl { public int getType() { return MESSAGE_TYPE; } + @Override public int hashCode() { return DataHelper.hashCode(getReceiveTunnelId()) + getStatus() + (int)getNonce(); } + @Override public boolean equals(Object object) { if ( (object != null) && (object instanceof TunnelCreateStatusMessage) ) { TunnelCreateStatusMessage msg = (TunnelCreateStatusMessage)object; @@ -104,6 +106,7 @@ public class TunnelCreateStatusMessage extends I2NPMessageImpl { } } + @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("[TunnelCreateStatusMessage: "); diff --git a/router/java/src/net/i2p/data/i2np/TunnelDataMessage.java b/router/java/src/net/i2p/data/i2np/TunnelDataMessage.java index a07b99069a0cce3a70aa40ac37149f3ec1e3918d..77c967f5871a3d19d772c479b9dab842033ab4b3 100644 --- a/router/java/src/net/i2p/data/i2np/TunnelDataMessage.java +++ b/router/java/src/net/i2p/data/i2np/TunnelDataMessage.java @@ -112,11 +112,13 @@ public class TunnelDataMessage extends I2NPMessageImpl { public int getType() { return MESSAGE_TYPE; } + @Override public int hashCode() { return (int)_tunnelId + DataHelper.hashCode(_data); } + @Override public boolean equals(Object object) { if ( (object != null) && (object instanceof TunnelDataMessage) ) { TunnelDataMessage msg = (TunnelDataMessage)object; @@ -127,6 +129,7 @@ public class TunnelDataMessage extends I2NPMessageImpl { } } + @Override public byte[] toByteArray() { byte rv[] = super.toByteArray(); if (rv == null) @@ -134,6 +137,7 @@ public class TunnelDataMessage extends I2NPMessageImpl { return rv; } + @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("[TunnelDataMessage:"); diff --git a/router/java/src/net/i2p/data/i2np/TunnelGatewayMessage.java b/router/java/src/net/i2p/data/i2np/TunnelGatewayMessage.java index 8fc7c9fd9e947c196ae771181396ad4682e76259..a436472e4319d679d1ff9d5ba3021a95cbb10d77 100644 --- a/router/java/src/net/i2p/data/i2np/TunnelGatewayMessage.java +++ b/router/java/src/net/i2p/data/i2np/TunnelGatewayMessage.java @@ -90,6 +90,7 @@ public class TunnelGatewayMessage extends I2NPMessageImpl { I2NPMessageHandler h = new I2NPMessageHandler(_context); readMessage(data, offset, dataSize, type, h); } + @Override public void readMessage(byte data[], int offset, int dataSize, int type, I2NPMessageHandler handler) throws I2NPMessageException, IOException { if (type != MESSAGE_TYPE) throw new I2NPMessageException("Message type is incorrect for this message"); int curIndex = offset; @@ -110,11 +111,13 @@ public class TunnelGatewayMessage extends I2NPMessageImpl { public int getType() { return MESSAGE_TYPE; } + @Override public int hashCode() { return DataHelper.hashCode(getTunnelId()) + DataHelper.hashCode(_msg); } + @Override public boolean equals(Object object) { if ( (object != null) && (object instanceof TunnelGatewayMessage) ) { TunnelGatewayMessage msg = (TunnelGatewayMessage)object; @@ -126,6 +129,7 @@ public class TunnelGatewayMessage extends I2NPMessageImpl { } } + @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("[TunnelGatewayMessage:"); diff --git a/router/java/src/net/i2p/data/i2np/TunnelSessionKey.java b/router/java/src/net/i2p/data/i2np/TunnelSessionKey.java index b73cbfa792037ad9d7154ed8b78522fcd6f21f22..c4effc3034ced8c3ea10419b6a9c1ccf1c058330 100644 --- a/router/java/src/net/i2p/data/i2np/TunnelSessionKey.java +++ b/router/java/src/net/i2p/data/i2np/TunnelSessionKey.java @@ -44,17 +44,20 @@ public class TunnelSessionKey extends DataStructureImpl { _key.writeBytes(out); } + @Override public boolean equals(Object obj) { if ( (obj == null) || !(obj instanceof TunnelSessionKey)) return false; return DataHelper.eq(getKey(), ((TunnelSessionKey)obj).getKey()); } + @Override public int hashCode() { if (_key == null) return 0; return getKey().hashCode(); } + @Override public String toString() { return "[TunnelSessionKey: " + getKey() + "]"; } diff --git a/router/java/src/net/i2p/data/i2np/TunnelSigningPrivateKey.java b/router/java/src/net/i2p/data/i2np/TunnelSigningPrivateKey.java index ec1f887465b7dccac4a65a842e8e699ed2f769d0..03d017915f8b242ddafd659ce412e0ed781a472b 100644 --- a/router/java/src/net/i2p/data/i2np/TunnelSigningPrivateKey.java +++ b/router/java/src/net/i2p/data/i2np/TunnelSigningPrivateKey.java @@ -45,17 +45,20 @@ public class TunnelSigningPrivateKey extends DataStructureImpl { _key.writeBytes(out); } + @Override public boolean equals(Object obj) { if ( (obj == null) || !(obj instanceof TunnelSigningPrivateKey)) return false; return DataHelper.eq(getKey(), ((TunnelSigningPrivateKey)obj).getKey()); } + @Override public int hashCode() { if (_key == null) return 0; return getKey().hashCode(); } + @Override public String toString() { return "[EndPointPrivateKey: " + getKey() + "]"; } diff --git a/router/java/src/net/i2p/data/i2np/TunnelSigningPublicKey.java b/router/java/src/net/i2p/data/i2np/TunnelSigningPublicKey.java index 9ce7e79adecc30fc5805b6f1cb121e66237e95e3..1f3530949226645b2d532685b39b92103ce7998d 100644 --- a/router/java/src/net/i2p/data/i2np/TunnelSigningPublicKey.java +++ b/router/java/src/net/i2p/data/i2np/TunnelSigningPublicKey.java @@ -44,17 +44,20 @@ public class TunnelSigningPublicKey extends DataStructureImpl { _key.writeBytes(out); } + @Override public boolean equals(Object obj) { if ( (obj == null) || !(obj instanceof TunnelSigningPublicKey)) return false; return DataHelper.eq(getKey(), ((TunnelSigningPublicKey)obj).getKey()); } + @Override public int hashCode() { if (_key == null) return 0; return getKey().hashCode(); } + @Override public String toString() { return "[TunnelSigningPublicKey: " + getKey() + "]"; } diff --git a/router/java/src/net/i2p/data/i2np/TunnelVerificationStructure.java b/router/java/src/net/i2p/data/i2np/TunnelVerificationStructure.java index aec62c93eb03b4970bb66353c112c35b211dce9f..7c2e4f00168a394b4cd295f8e350eb0ef22fadc1 100644 --- a/router/java/src/net/i2p/data/i2np/TunnelVerificationStructure.java +++ b/router/java/src/net/i2p/data/i2np/TunnelVerificationStructure.java @@ -69,6 +69,7 @@ public class TunnelVerificationStructure extends DataStructureImpl { _authSignature.writeBytes(out); } + @Override public boolean equals(Object obj) { if ( (obj == null) || !(obj instanceof TunnelVerificationStructure)) return false; @@ -77,11 +78,13 @@ public class TunnelVerificationStructure extends DataStructureImpl { DataHelper.eq(getAuthorizationSignature(), str.getAuthorizationSignature()); } + @Override public int hashCode() { if ( (_msgHash == null) || (_authSignature == null) ) return 0; return getMessageHash().hashCode() + getAuthorizationSignature().hashCode(); } + @Override public String toString() { return "[TunnelVerificationStructure: " + getMessageHash() + " " + getAuthorizationSignature() + "]"; } diff --git a/router/java/src/net/i2p/router/Blocklist.java b/router/java/src/net/i2p/router/Blocklist.java index 4e94d77095aeaebaf4b02947503e1f6cea5c7ad4..7546ac4a713494b9b61de6da9efeda60996bb70a 100644 --- a/router/java/src/net/i2p/router/Blocklist.java +++ b/router/java/src/net/i2p/router/Blocklist.java @@ -13,14 +13,13 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.*; -import net.i2p.I2PAppContext; import net.i2p.data.Base64; import net.i2p.data.DataHelper; import net.i2p.data.Hash; import net.i2p.data.RouterAddress; import net.i2p.data.RouterInfo; import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade; -import net.i2p.util.HexDump; +import net.i2p.util.ConcurrentHashSet; import net.i2p.util.Log; /** @@ -55,22 +54,18 @@ public class Blocklist { private RouterContext _context; private long _blocklist[]; private int _blocklistSize; - private Object _lock; + private final Object _lock = new Object(); private Entry _wrapSave; - private Set _inProcess; - private Map _peerBlocklist; - private Set _singleIPBlocklist; + private final Set<Hash> _inProcess = new HashSet(0); + private Map<Hash, String> _peerBlocklist = new HashMap(0); + private final Set<Integer> _singleIPBlocklist = new ConcurrentHashSet(0); public Blocklist(RouterContext context) { _context = context; _log = context.logManager().getLog(Blocklist.class); _blocklist = null; _blocklistSize = 0; - _lock = new Object(); _wrapSave = null; - _inProcess = new HashSet(0); - _peerBlocklist = new HashMap(0); - _singleIPBlocklist = new HashSet(0); } public Blocklist() { @@ -448,15 +443,11 @@ public class Blocklist { } private boolean add(int ip) { - synchronized(_singleIPBlocklist) { - return _singleIPBlocklist.add(new Integer(ip)); - } + return _singleIPBlocklist.add(Integer.valueOf(ip)); } private boolean isOnSingleList(int ip) { - synchronized(_singleIPBlocklist) { - return _singleIPBlocklist.contains(new Integer(ip)); - } + return _singleIPBlocklist.contains(Integer.valueOf(ip)); } /** @@ -588,11 +579,11 @@ public class Blocklist { // methods to get and store the from/to values in the array - private int getFrom(long entry) { + private static int getFrom(long entry) { return (int) ((entry >> 32) & 0xffffffff); } - private int getTo(long entry) { + private static int getTo(long entry) { return (int) (entry & 0xffffffff); } @@ -604,7 +595,7 @@ public class Blocklist { * So the size is (cough) almost 2MB for the 240,000 line splist.txt. * */ - private long toEntry(byte ip1[], byte ip2[]) { + private static long toEntry(byte ip1[], byte ip2[]) { long entry = 0; for (int i = 0; i < 4; i++) entry |= ((long) (ip2[i] & 0xff)) << ((3-i)*8); @@ -623,14 +614,18 @@ public class Blocklist { _blocklist[idx] = entry; } - private int toInt(byte ip[]) { + private static int toInt(byte ip[]) { int rv = 0; for (int i = 0; i < 4; i++) rv |= (ip[i] & 0xff) << ((3-i)*8); return rv; } - private String toStr(long entry) { + public static String toStr(byte[] ip) { + return toStr(toInt(ip)); + } + + private static String toStr(long entry) { StringBuffer buf = new StringBuffer(32); for (int i = 7; i >= 0; i--) { buf.append((entry >> (8*i)) & 0xff); @@ -642,7 +637,7 @@ public class Blocklist { return buf.toString(); } - private String toStr(int ip) { + private static String toStr(int ip) { StringBuffer buf = new StringBuffer(16); for (int i = 3; i >= 0; i--) { buf.append((ip >> (8*i)) & 0xff); @@ -758,9 +753,7 @@ public class Blocklist { public void renderStatusHTML(Writer out) throws IOException { out.write("<h2>IP Blocklist</h2>"); Set singles = new TreeSet(); - synchronized(_singleIPBlocklist) { - singles.addAll(_singleIPBlocklist); - } + singles.addAll(_singleIPBlocklist); if (singles.size() > 0) { out.write("<table><tr><td><b>Transient IPs</b></td></tr>"); for (Iterator iter = singles.iterator(); iter.hasNext(); ) { diff --git a/router/java/src/net/i2p/router/ClientTunnelSettings.java b/router/java/src/net/i2p/router/ClientTunnelSettings.java index e0f95e611bc3e19ec2b22ebb6ec5069816c69bce..6cd3981954c642a23d53395f4b649dd98fe8f15b 100644 --- a/router/java/src/net/i2p/router/ClientTunnelSettings.java +++ b/router/java/src/net/i2p/router/ClientTunnelSettings.java @@ -44,6 +44,7 @@ public class ClientTunnelSettings { _outboundSettings.writeToProperties("outbound.", props); } + @Override public String toString() { StringBuffer buf = new StringBuffer(); Properties p = new Properties(); diff --git a/router/java/src/net/i2p/router/CommSystemFacade.java b/router/java/src/net/i2p/router/CommSystemFacade.java index 6d0927c63ec51cb039a6120ffecf3cf0a92211f9..f3535cf4c89b108292fdd7cbcd1202a7e8510982 100644 --- a/router/java/src/net/i2p/router/CommSystemFacade.java +++ b/router/java/src/net/i2p/router/CommSystemFacade.java @@ -58,6 +58,7 @@ public abstract class CommSystemFacade implements Service { public boolean isBacklogged(Hash dest) { return false; } public boolean wasUnreachable(Hash dest) { return false; } public boolean isEstablished(Hash dest) { return false; } + public byte[] getIP(Hash dest) { return null; } /** * Tell other transports our address changed diff --git a/router/java/src/net/i2p/router/InNetMessagePool.java b/router/java/src/net/i2p/router/InNetMessagePool.java index 4ab5c77b41d1d190e99e04bf2bcce80e8d15f1f7..802aedec0a6903aa2b15dc2fbd837073a00cdb62 100644 --- a/router/java/src/net/i2p/router/InNetMessagePool.java +++ b/router/java/src/net/i2p/router/InNetMessagePool.java @@ -35,9 +35,9 @@ public class InNetMessagePool implements Service { private Log _log; private RouterContext _context; private HandlerJobBuilder _handlerJobBuilders[]; - private List _pendingDataMessages; - private List _pendingDataMessagesFrom; - private List _pendingGatewayMessages; + private final List _pendingDataMessages; + private final List _pendingDataMessagesFrom; + private final List _pendingGatewayMessages; private SharedShortCircuitDataJob _shortCircuitDataJob; private SharedShortCircuitGatewayJob _shortCircuitGatewayJob; private boolean _alive; diff --git a/router/java/src/net/i2p/router/JobImpl.java b/router/java/src/net/i2p/router/JobImpl.java index 84190940bbbea99ae9273ea36535452ba433bcdd..a72f852967f3053345d2ba8b811a36787a1baae9 100644 --- a/router/java/src/net/i2p/router/JobImpl.java +++ b/router/java/src/net/i2p/router/JobImpl.java @@ -33,6 +33,7 @@ public abstract class JobImpl implements Job { public final RouterContext getContext() { return _context; } + @Override public String toString() { StringBuffer buf = new StringBuffer(128); buf.append(super.toString()); diff --git a/router/java/src/net/i2p/router/JobQueue.java b/router/java/src/net/i2p/router/JobQueue.java index 915288cc667899c9afcf415302b96da26833beab..8ec40f56e51d7c3243274fc145cf627879d88869 100644 --- a/router/java/src/net/i2p/router/JobQueue.java +++ b/router/java/src/net/i2p/router/JobQueue.java @@ -33,7 +33,7 @@ public class JobQueue { private RouterContext _context; /** Integer (runnerId) to JobQueueRunner for created runners */ - private HashMap _queueRunners; + private final HashMap _queueRunners; /** a counter to identify a job runner */ private volatile static int _runnerId = 0; /** list of jobs that are ready to run ASAP */ @@ -41,7 +41,7 @@ public class JobQueue { /** list of jobs that are scheduled for running in the future */ private ArrayList _timedJobs; /** job name to JobStat for that job */ - private SortedMap _jobStats; + private final SortedMap _jobStats; /** how many job queue runners can go concurrently */ private int _maxRunners = 1; private QueuePumper _pumper; @@ -50,7 +50,7 @@ public class JobQueue { /** have we been killed or are we alive? */ private boolean _alive; - private Object _jobLock; + private final Object _jobLock; /** default max # job queue runners operating */ private final static int DEFAULT_MAX_RUNNERS = 1; @@ -94,7 +94,7 @@ public class JobQueue { * queue runners wait on this whenever they're not doing anything, and * this gets notified *once* whenever there are ready jobs */ - private Object _runnerLock = new Object(); + private final Object _runnerLock = new Object(); public JobQueue(RouterContext context) { _context = context; diff --git a/router/java/src/net/i2p/router/JobStats.java b/router/java/src/net/i2p/router/JobStats.java index d3cf345d0253eeb08a5600df8375958099d9dbdd..ec571299311603df7e0e13c74999b8e1d6019931 100644 --- a/router/java/src/net/i2p/router/JobStats.java +++ b/router/java/src/net/i2p/router/JobStats.java @@ -59,7 +59,9 @@ class JobStats { return 0; } + @Override public int hashCode() { return _job.hashCode(); } + @Override public boolean equals(Object obj) { if ( (obj != null) && (obj instanceof JobStats) ) { JobStats stats = (JobStats)obj; @@ -73,6 +75,7 @@ class JobStats { } } + @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("Over ").append(getRuns()).append(" runs, job <b>").append(getName()).append("</b> took "); diff --git a/router/java/src/net/i2p/router/KeyManager.java b/router/java/src/net/i2p/router/KeyManager.java index 4e2ed2c51891800665b5dbda10a52113538bcb37..9fc62a70f29a0213f450a8109faa26d13cd80e3d 100644 --- a/router/java/src/net/i2p/router/KeyManager.java +++ b/router/java/src/net/i2p/router/KeyManager.java @@ -41,7 +41,7 @@ public class KeyManager { private PublicKey _publicKey; private SigningPrivateKey _signingPrivateKey; private SigningPublicKey _signingPublicKey; - private Map _leaseSetKeys; // Destination --> LeaseSetKeys + private final Map _leaseSetKeys; // Destination --> LeaseSetKeys private SynchronizeKeysJob _synchronizeJob; public final static String PROP_KEYDIR = "router.keyBackupDir"; diff --git a/router/java/src/net/i2p/router/LeaseSetKeys.java b/router/java/src/net/i2p/router/LeaseSetKeys.java index c88b0808afed3650f338c4b556d4b86fbc095af3..1017ab43db5c322d7b6e47488a40bad0013ae6fd 100644 --- a/router/java/src/net/i2p/router/LeaseSetKeys.java +++ b/router/java/src/net/i2p/router/LeaseSetKeys.java @@ -73,6 +73,7 @@ public class LeaseSetKeys extends DataStructureImpl { _revocationKey.writeBytes(out); } + @Override public int hashCode() { int rv = 0; rv += DataHelper.hashCode(_dest); @@ -81,6 +82,7 @@ public class LeaseSetKeys extends DataStructureImpl { return rv; } + @Override public boolean equals(Object obj) { if ( (obj != null) && (obj instanceof LeaseSetKeys) ) { LeaseSetKeys keys = (LeaseSetKeys)obj; diff --git a/router/java/src/net/i2p/router/MessageHistory.java b/router/java/src/net/i2p/router/MessageHistory.java index d88d653de03ff70c24e358f5931d82c5edac73d2..cafbadd1cd5bb0cb23ce3725d9536c29c47e522c 100644 --- a/router/java/src/net/i2p/router/MessageHistory.java +++ b/router/java/src/net/i2p/router/MessageHistory.java @@ -26,7 +26,7 @@ import net.i2p.util.Log; public class MessageHistory { private Log _log; private RouterContext _context; - private List _unwrittenEntries; // list of raw entries (strings) yet to be written + private final List _unwrittenEntries = new ArrayList(64); // list of raw entries (strings) yet to be written private String _historyFile; // where to write private String _localIdent; // placed in each entry to uniquely identify the local router private boolean _doLog; // true == we want to log @@ -104,7 +104,7 @@ public class MessageHistory { _doLog = DEFAULT_KEEP_MESSAGE_HISTORY; _historyFile = filename; _localIdent = getName(_context.routerHash()); - _unwrittenEntries = new ArrayList(64); + // _unwrittenEntries = new ArrayList(64); updateSettings(); // clear the history file on startup if (_firstPass) { diff --git a/router/java/src/net/i2p/router/MultiRouter.java b/router/java/src/net/i2p/router/MultiRouter.java index 144c4e1db8a9059f9d92d66ded03f5c306e2d1ea..d8d316ae8aa0291d51e3ce370f0fb7aea4d553b6 100644 --- a/router/java/src/net/i2p/router/MultiRouter.java +++ b/router/java/src/net/i2p/router/MultiRouter.java @@ -58,6 +58,7 @@ public class MultiRouter { _defaultContext.clock().setOffset(0); Runtime.getRuntime().addShutdownHook(new Thread() { + @Override public void run() { Thread.currentThread().setName("Router* Shutdown"); try { Thread.sleep(120*1000); } catch (InterruptedException ie) {} diff --git a/router/java/src/net/i2p/router/NetworkDatabaseFacade.java b/router/java/src/net/i2p/router/NetworkDatabaseFacade.java index e4a5ce08b663a7da1c9fc9752104dc33875bae0a..ded9bee26a7a9f1445c440465d9f7a819af3b9b4 100644 --- a/router/java/src/net/i2p/router/NetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/NetworkDatabaseFacade.java @@ -10,10 +10,6 @@ package net.i2p.router; import java.io.IOException; import java.io.Writer; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; import java.util.Set; import net.i2p.data.Hash; @@ -62,5 +58,6 @@ public abstract class NetworkDatabaseFacade implements Service { public int getKnownRouters() { return 0; } public int getKnownLeaseSets() { return 0; } public void renderRouterInfoHTML(Writer out, String s) throws IOException {} + public void renderLeaseSetHTML(Writer out) throws IOException {} public void renderStatusHTML(Writer out, boolean b) throws IOException {} } diff --git a/router/java/src/net/i2p/router/OutNetMessage.java b/router/java/src/net/i2p/router/OutNetMessage.java index 2240af423c2465094b244823441be641b505b4ff..e1cd2a896622d6aa3489375315f843f36ec725b5 100644 --- a/router/java/src/net/i2p/router/OutNetMessage.java +++ b/router/java/src/net/i2p/router/OutNetMessage.java @@ -302,6 +302,7 @@ public class OutNetMessage { super.finalize(); } */ + @Override public String toString() { StringBuffer buf = new StringBuffer(128); buf.append("[OutNetMessage contains "); @@ -365,6 +366,7 @@ public class OutNetMessage { } } + @Override public int hashCode() { int rv = 0; rv += DataHelper.hashCode(_message); @@ -373,7 +375,10 @@ public class OutNetMessage { return rv; } + @Override public boolean equals(Object obj) { + if(obj == null) return false; + if(obj.getClass() != OutNetMessage.class) return false; return obj == this; // two OutNetMessages are different even if they contain the same message } } diff --git a/router/java/src/net/i2p/router/PeerManagerFacade.java b/router/java/src/net/i2p/router/PeerManagerFacade.java index 791b77616a5600e669af4a103bd37bf92e2a4efc..61b1d3799e5d56a9c2d5d10cb09c609bb85e9605 100644 --- a/router/java/src/net/i2p/router/PeerManagerFacade.java +++ b/router/java/src/net/i2p/router/PeerManagerFacade.java @@ -8,7 +8,6 @@ package net.i2p.router; * */ -import java.io.Writer; import java.util.List; import net.i2p.data.Hash; diff --git a/router/java/src/net/i2p/router/PersistentKeyRing.java b/router/java/src/net/i2p/router/PersistentKeyRing.java index d02275ea20c72bbb045269d74e52ac1d494ff1df..f1f4fe55a117bfb0fb09714b14f41c8aad871b68 100644 --- a/router/java/src/net/i2p/router/PersistentKeyRing.java +++ b/router/java/src/net/i2p/router/PersistentKeyRing.java @@ -4,16 +4,12 @@ import java.io.IOException; import java.io.Writer; import java.util.Iterator; -import java.util.Map; -import java.util.TreeMap; -import net.i2p.data.Base64; import net.i2p.data.DataFormatException; import net.i2p.data.Destination; import net.i2p.data.Hash; import net.i2p.data.LeaseSet; import net.i2p.data.SessionKey; -import net.i2p.router.TunnelPoolSettings; import net.i2p.util.KeyRing; /** @@ -31,6 +27,7 @@ public class PersistentKeyRing extends KeyRing { addFromProperties(); } + @Override public SessionKey put(Hash h, SessionKey sk) { SessionKey old = super.put(h, sk); if (!sk.equals(old)) { @@ -67,6 +64,7 @@ public class PersistentKeyRing extends KeyRing { } } + @Override public void renderStatusHTML(Writer out) throws IOException { StringBuffer buf = new StringBuffer(1024); buf.append("\n<table border=\"1\"><tr><th align=\"left\">Destination Hash<th align=\"left\">Name or Dest.<th align=\"left\">Session Key</tr>"); diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index 37215f6c4b579129da3ee6ea784ebd72820a74e9..c9a95dd552208c43145fa8b634cb375b7656635f 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -9,7 +9,6 @@ package net.i2p.router; */ import java.io.File; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.Writer; @@ -53,7 +52,7 @@ import net.i2p.util.SimpleTimer; public class Router { private Log _log; private RouterContext _context; - private Properties _config; + private final Properties _config; private String _configFilename; private RouterInfo _routerInfo; private long _started; @@ -64,7 +63,7 @@ public class Router { private int _gracefulExitCode; private I2PThread.OOMEventListener _oomListener; private ShutdownHook _shutdownHook; - private I2PThread _gracefulShutdownDetector; + private final I2PThread _gracefulShutdownDetector; public final static String PROP_CONFIG_FILE = "router.configLocation"; @@ -686,6 +685,7 @@ public class Router { out.write("\n<hr /><a name=\"netdb\"> </a>\n"); + _context.netDb().renderLeaseSetHTML(out); _context.netDb().renderStatusHTML(out); buf.setLength(0); @@ -1350,6 +1350,7 @@ private static class ShutdownHook extends Thread { _context = ctx; _id = ++__id; } + @Override public void run() { setName("Router " + _id + " shutdown"); Log l = _context.logManager().getLog(Router.class); diff --git a/router/java/src/net/i2p/router/RouterClock.java b/router/java/src/net/i2p/router/RouterClock.java index 3174e60276db72a52c40fedd1bf9d140d306dd99..d071013b2d3b13d0553f30560bd97c67b5a4bfbe 100644 --- a/router/java/src/net/i2p/router/RouterClock.java +++ b/router/java/src/net/i2p/router/RouterClock.java @@ -15,11 +15,11 @@ import net.i2p.util.Log; */ public class RouterClock extends Clock { - RouterContext _context; + RouterContext _contextRC; // LINT field hides another field public RouterClock(RouterContext context) { super(context); - _context = context; + _contextRC = context; } /** @@ -27,6 +27,7 @@ public class RouterClock extends Clock { * value means that we are slow, while a negative value means we are fast. * */ + @Override public void setOffset(long offsetMs, boolean force) { if (false) return; @@ -53,10 +54,10 @@ public class RouterClock extends Clock { } // If so configured, check sanity of proposed clock offset - if (Boolean.valueOf(_context.getProperty("router.clockOffsetSanityCheck","true")).booleanValue() == true) { + if (Boolean.valueOf(_contextRC.getProperty("router.clockOffsetSanityCheck","true")).booleanValue() == true) { // Try calculating peer clock skew - Long peerClockSkew = _context.commSystem().getFramedAveragePeerClockSkew(50); + Long peerClockSkew = _contextRC.commSystem().getFramedAveragePeerClockSkew(50); if (peerClockSkew != null) { @@ -88,9 +89,9 @@ public class RouterClock extends Clock { getLog().info("Updating clock offset to " + offsetMs + "ms from " + _offset + "ms"); if (!_statCreated) - _context.statManager().createRateStat("clock.skew", "How far is the already adjusted clock being skewed?", "Clock", new long[] { 10*60*1000, 3*60*60*1000, 24*60*60*60 }); + _contextRC.statManager().createRateStat("clock.skew", "How far is the already adjusted clock being skewed?", "Clock", new long[] { 10*60*1000, 3*60*60*1000, 24*60*60*60 }); _statCreated = true; - _context.statManager().addRateData("clock.skew", delta, 0); + _contextRC.statManager().addRateData("clock.skew", delta, 0); } else { getLog().log(Log.INFO, "Initializing clock offset to " + offsetMs + "ms from " + _offset + "ms"); } diff --git a/router/java/src/net/i2p/router/RouterContext.java b/router/java/src/net/i2p/router/RouterContext.java index ba82fb839365677049205a9b15c7231037903dcc..782bc8a87550fffd01b3620a64e587a4aae36f12 100644 --- a/router/java/src/net/i2p/router/RouterContext.java +++ b/router/java/src/net/i2p/router/RouterContext.java @@ -58,7 +58,7 @@ public class RouterContext extends I2PAppContext { private MessageValidator _messageValidator; private MessageStateMonitor _messageStateMonitor; private RouterThrottle _throttle; - private RouterClock _clock; + private RouterClock _clockX; // LINT field hides another field, hope rename won't break anything. private Calculator _integrationCalc; private Calculator _speedCalc; private Calculator _capacityCalc; @@ -262,6 +262,7 @@ public class RouterContext extends I2PAppContext { /** how do we rank the capacity of profiles? */ public Calculator capacityCalculator() { return _capacityCalc; } + @Override public String toString() { StringBuffer buf = new StringBuffer(512); buf.append("RouterContext: ").append(super.toString()).append('\n'); @@ -294,6 +295,7 @@ public class RouterContext extends I2PAppContext { * I2PAppContext says. * */ + @Override public String getProperty(String propName) { if (_router != null) { String val = _router.getConfigSetting(propName); @@ -306,6 +308,7 @@ public class RouterContext extends I2PAppContext { * I2PAppContext says. * */ + @Override public String getProperty(String propName, String defaultVal) { if (_router != null) { String val = _router.getConfigSetting(propName); @@ -317,6 +320,7 @@ public class RouterContext extends I2PAppContext { /** * Return an int with an int default */ + @Override public int getProperty(String propName, int defaultVal) { if (_router != null) { String val = _router.getConfigSetting(propName); @@ -339,14 +343,16 @@ public class RouterContext extends I2PAppContext { * that it triggers initializeClock() of which we definitely * need the local version to run. */ + @Override public Clock clock() { if (!_clockInitialized) initializeClock(); - return _clock; + return _clockX; } + @Override protected void initializeClock() { synchronized (this) { - if (_clock == null) - _clock = new RouterClock(this); + if (_clockX == null) + _clockX = new RouterClock(this); _clockInitialized = true; } } diff --git a/router/java/src/net/i2p/router/RouterDoSThrottle.java b/router/java/src/net/i2p/router/RouterDoSThrottle.java index c161ddda584547957b42f5e30b0440afbde5ff7e..79471627a24996782fc018d6d0a5616812c7a887 100644 --- a/router/java/src/net/i2p/router/RouterDoSThrottle.java +++ b/router/java/src/net/i2p/router/RouterDoSThrottle.java @@ -19,6 +19,7 @@ class RouterDoSThrottle extends RouterThrottleImpl { private static final long LOOKUP_THROTTLE_PERIOD = 10*1000; private static final long LOOKUP_THROTTLE_MAX = 20; + @Override public boolean acceptNetDbLookupRequest(Hash key) { // if we were going to refuse it anyway, drop it boolean shouldAccept = super.acceptNetDbLookupRequest(key); diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index eb1429483320cb8aa87d2acdcfebd2fb90998a18..5203f2360b8c639e5b7467177c7101dc9a20b67e 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -17,7 +17,7 @@ import net.i2p.CoreVersion; public class RouterVersion { public final static String ID = "$Revision: 1.548 $ $Date: 2008-06-07 23:00:00 $"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 21; + public final static long BUILD = 5; public static void main(String args[]) { System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("Router ID: " + RouterVersion.ID); diff --git a/router/java/src/net/i2p/router/Shitlist.java b/router/java/src/net/i2p/router/Shitlist.java index 29d384de90acc327720d158a3e145bfe443f7a05..1416cc9fe4dc5dda858680187d4a3e16c951341b 100644 --- a/router/java/src/net/i2p/router/Shitlist.java +++ b/router/java/src/net/i2p/router/Shitlist.java @@ -13,8 +13,6 @@ import java.io.Writer; import java.util.concurrent.ConcurrentHashMap; import java.util.ArrayList; import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; diff --git a/router/java/src/net/i2p/router/StatisticsManager.java b/router/java/src/net/i2p/router/StatisticsManager.java index 4a286fe3d07747d014e124d7b9e43a076beb8f3a..d037ee300eabf11255b5e2eba528be61abdd1110 100644 --- a/router/java/src/net/i2p/router/StatisticsManager.java +++ b/router/java/src/net/i2p/router/StatisticsManager.java @@ -53,8 +53,6 @@ public class StatisticsManager implements Service { _includePeerRankings = Boolean.valueOf(val); } - static final boolean CommentOutIn072 = RouterVersion.VERSION.equals("0.7.1"); - /** Retrieve a snapshot of the statistics that should be published */ public Properties publishStatistics() { Properties stats = new Properties(); @@ -123,7 +121,7 @@ public class StatisticsManager implements Service { //includeRate("transport.sendProcessingTime", stats, new long[] { 60*60*1000 }); //includeRate("jobQueue.jobRunSlow", stats, new long[] { 10*60*1000l, 60*60*1000l }); //includeRate("crypto.elGamal.encrypt", stats, new long[] { 60*60*1000 }); - includeRate("tunnel.participatingTunnels", stats, new long[] { 5*60*1000, 60*60*1000 }); + includeRate("tunnel.participatingTunnels", stats, new long[] { 60*60*1000 }); //includeRate("tunnel.testSuccessTime", stats, new long[] { 10*60*1000l }); //includeRate("client.sendAckTime", stats, new long[] { 60*60*1000 }, true); //includeRate("udp.sendConfirmTime", stats, new long[] { 10*60*1000 }); @@ -133,16 +131,6 @@ public class StatisticsManager implements Service { //includeRate("stream.con.sendDuplicateSize", stats, new long[] { 60*60*1000 }); //includeRate("stream.con.receiveDuplicateSize", stats, new long[] { 60*60*1000 }); - if (CommentOutIn072) { - // Round smaller uptimes to 1 hour, to frustrate uptime tracking - // Round 2nd hour to 90m since peers use 2h minimum to route - if (publishedUptime < 60*60*1000) publishedUptime = 60*60*1000; - else if (publishedUptime < 2*60*60*1000) publishedUptime = 90*60*1000; - stats.setProperty("stat_uptime", DataHelper.formatDuration(publishedUptime)); - } else { - // So that we will still get build requests - stats.setProperty("stat_uptime", "90m"); - } //stats.setProperty("stat__rateKey", "avg;maxAvg;pctLifetime;[sat;satLim;maxSat;maxSatLim;][num;lifetimeFreq;maxFreq]"); //includeRate("tunnel.decryptRequestTime", stats, new long[] { 60*1000, 10*60*1000 }); @@ -150,7 +138,7 @@ public class StatisticsManager implements Service { //includeRate("udp.packetVerifyTime", stats, new long[] { 60*1000 }); //includeRate("tunnel.buildRequestTime", stats, new long[] { 10*60*1000 }); - long rate = CommentOutIn072 ? 10*60*1000 : 60*60*1000; + long rate = 60*60*1000; includeRate("tunnel.buildClientExpire", stats, new long[] { rate }); includeRate("tunnel.buildClientReject", stats, new long[] { rate }); includeRate("tunnel.buildClientSuccess", stats, new long[] { rate }); @@ -160,20 +148,15 @@ public class StatisticsManager implements Service { //includeRate("tunnel.rejectTimeout", stats, new long[] { 10*60*1000 }); //includeRate("tunnel.rejectOverloaded", stats, new long[] { 10*60*1000 }); //includeRate("tunnel.acceptLoad", stats, new long[] { 10*60*1000 }); - - _log.debug("Publishing peer rankings"); - } else { - // So that we will still get build requests - stats.setProperty("stat_uptime", "90m"); - _log.debug("Not publishing peer rankings"); } + + // So that we will still get build requests + stats.setProperty("stat_uptime", "90m"); if (FloodfillNetworkDatabaseFacade.isFloodfill(_context.router().getRouterInfo())) { stats.setProperty("netdb.knownRouters", ""+_context.netDb().getKnownRouters()); stats.setProperty("netdb.knownLeaseSets", ""+_context.netDb().getKnownLeaseSets()); } - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Building status: " + stats); return stats; } diff --git a/router/java/src/net/i2p/router/TunnelManagerFacade.java b/router/java/src/net/i2p/router/TunnelManagerFacade.java index da0482e6ffd4072eac1416e95e3397cf0222fd20..8ddc1e060f59ea9fdcafb1488024b1374a749ce1 100644 --- a/router/java/src/net/i2p/router/TunnelManagerFacade.java +++ b/router/java/src/net/i2p/router/TunnelManagerFacade.java @@ -8,8 +8,6 @@ package net.i2p.router; * */ -import java.io.IOException; -import java.io.Writer; import java.util.Set; import net.i2p.data.Destination; diff --git a/router/java/src/net/i2p/router/TunnelPoolSettings.java b/router/java/src/net/i2p/router/TunnelPoolSettings.java index a92470d2ee14114fd8095016a7fece2558bc2ee1..fab33d919a077b1d5af69126aca2e734f66fcc2b 100644 --- a/router/java/src/net/i2p/router/TunnelPoolSettings.java +++ b/router/java/src/net/i2p/router/TunnelPoolSettings.java @@ -185,6 +185,7 @@ public class TunnelPoolSettings { } } + @Override public String toString() { StringBuffer buf = new StringBuffer(); Properties p = new Properties(); diff --git a/router/java/src/net/i2p/router/TunnelSettings.java b/router/java/src/net/i2p/router/TunnelSettings.java index 3ea8baa5671fe87e4846a47f69919bcad2a22c7c..99249f7c75f3c7042349711874b7e54b81e26ba3 100644 --- a/router/java/src/net/i2p/router/TunnelSettings.java +++ b/router/java/src/net/i2p/router/TunnelSettings.java @@ -105,6 +105,7 @@ public class TunnelSettings extends DataStructureImpl { } + @Override public int hashCode() { int rv = 0; rv += _includeDummy ? 100 : 0; @@ -118,6 +119,7 @@ public class TunnelSettings extends DataStructureImpl { return rv; } + @Override public boolean equals(Object obj) { if ( (obj != null) && (obj instanceof TunnelSettings) ) { TunnelSettings settings = (TunnelSettings)obj; diff --git a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java index 4f979c5c937a28a5638ebbf46a3398e1a33d3e80..5611f13774680f50cbf22d1743f6e6e3b6d5d78a 100644 --- a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java +++ b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java @@ -13,7 +13,6 @@ import java.io.OutputStream; import java.net.Socket; import java.util.concurrent.ConcurrentHashMap; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -73,7 +72,7 @@ public class ClientConnectionRunner { * This contains the last 10 MessageIds that have had their (non-ack) status * delivered to the client (so that we can be sure only to update when necessary) */ - private List _alreadyProcessed; + private final List _alreadyProcessed; private ClientWriterRunner _writer; private Hash _destHashCache; /** are we, uh, dead */ @@ -111,7 +110,7 @@ public class ClientConnectionRunner { t.setDaemon(true); t.setPriority(I2PThread.MAX_PRIORITY); t.start(); - _out = _socket.getOutputStream(); + _out = _socket.getOutputStream(); // LINT -- OWCH! needs a better way so it can be final. _reader.startReading(); } catch (IOException ioe) { _log.error("Error starting up the runner", ioe); @@ -412,7 +411,7 @@ public class ClientConnectionRunner { } if (_log.shouldLog(Log.DEBUG)) _log.debug("after writeMessage("+ msg.getClass().getName() + "): " - + (_context.clock().now()-before) + "ms");; + + (_context.clock().now()-before) + "ms"); } catch (I2CPMessageException ime) { _log.error("Message exception sending I2CP message: " + ime); stopRunning(); @@ -464,7 +463,7 @@ public class ClientConnectionRunner { // this *should* be mod 65536, but UnsignedInteger is still b0rked. FIXME private final static int MAX_MESSAGE_ID = 32767; private static volatile int _messageId = RandomSource.getInstance().nextInt(MAX_MESSAGE_ID); // messageId counter - private static Object _messageIdLock = new Object(); + private final static Object _messageIdLock = new Object(); static int getNextMessageId() { synchronized (_messageIdLock) { diff --git a/router/java/src/net/i2p/router/client/ClientManager.java b/router/java/src/net/i2p/router/client/ClientManager.java index 9b5eb7c4ccbe24886646d0c011f1aeceba41ee6d..85e7d9ec76c0bd7cf8dea1608af4b35d89e72a31 100644 --- a/router/java/src/net/i2p/router/client/ClientManager.java +++ b/router/java/src/net/i2p/router/client/ClientManager.java @@ -41,8 +41,8 @@ import net.i2p.util.Log; public class ClientManager { private Log _log; private ClientListenerRunner _listener; - private HashMap _runners; // Destination --> ClientConnectionRunner - private Set _pendingRunners; // ClientConnectionRunner for clients w/out a Dest yet + private final HashMap _runners; // Destination --> ClientConnectionRunner + private final Set _pendingRunners; // ClientConnectionRunner for clients w/out a Dest yet private RouterContext _ctx; /** ms to wait before rechecking for inbound messages to deliver to clients */ diff --git a/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java b/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java index 51b8b4cb2513a67ba24cd2b44fb41f42af5102c8..eddf13dd8e8d672e31cc5679811f390e3d2e8fef 100644 --- a/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java +++ b/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java @@ -74,9 +74,11 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade { startup(); } + @Override public boolean isAlive() { return _manager != null && _manager.isAlive(); } private static final long MAX_TIME_TO_REBUILD = 10*60*1000; + @Override public boolean verifyClientLiveliness() { if (_manager == null) return true; boolean lively = true; @@ -167,6 +169,7 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade { } } + @Override public boolean shouldPublishLeaseSet(Hash destinationHash) { return _manager.shouldPublishLeaseSet(destinationHash); } public void messageDeliveryStatusUpdate(Destination fromDest, MessageId id, boolean delivered) { @@ -196,6 +199,7 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade { } } + @Override public void renderStatusHTML(Writer out) throws IOException { if (_manager != null) _manager.renderStatusHTML(out); @@ -206,6 +210,7 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade { * * @return set of Destination objects */ + @Override public Set listClients() { if (_manager != null) return _manager.listClients(); diff --git a/router/java/src/net/i2p/router/message/CloveSet.java b/router/java/src/net/i2p/router/message/CloveSet.java index 1774c9be02a6640cc8da59615e5f644ed524caed..d18aa55b44baed89829747cf5e0b0b4475ec8784 100644 --- a/router/java/src/net/i2p/router/message/CloveSet.java +++ b/router/java/src/net/i2p/router/message/CloveSet.java @@ -42,6 +42,7 @@ public class CloveSet { public long getExpiration() { return _expiration; } public void setExpiration(long expiration) { _expiration = expiration; } + @Override public String toString() { StringBuffer buf = new StringBuffer(128); buf.append("{"); diff --git a/router/java/src/net/i2p/router/message/GarlicConfig.java b/router/java/src/net/i2p/router/message/GarlicConfig.java index 3b6359a89d4c2b72955ebf0c7a086da536902c04..ead346e0067f239af6f7caca0acdab0f66f549e9 100644 --- a/router/java/src/net/i2p/router/message/GarlicConfig.java +++ b/router/java/src/net/i2p/router/message/GarlicConfig.java @@ -156,6 +156,7 @@ public class GarlicConfig { protected String getSubData() { return ""; } private final static String NL = System.getProperty("line.separator"); + @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("<garlicConfig>").append(NL); diff --git a/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java b/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java index 5d6b37a96c140a9bb26e072268077f4afed409bf..2a04de8e4edbc3526d921953af741063d9df086b 100644 --- a/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java +++ b/router/java/src/net/i2p/router/message/GarlicMessageBuilder.java @@ -30,6 +30,37 @@ import net.i2p.util.Log; * */ public class GarlicMessageBuilder { + + /** + * This was 100 since 0.6.1.10 (50 before that). It's important because: + * - Tags are 32 bytes. So it previously added 3200 bytes to an initial message. + * - Too many tags adds a huge overhead to short-duration connections + * (like http, datagrams, etc.) + * - Large messages have a much higher chance of being dropped due to + * one of their 1KB fragments being discarded by a tunnel participant. + * - This reduces the effective maximum datagram size because the client + * doesn't know when tags will be bundled, so the tag size must be + * subtracted from the maximum I2NP size or transport limit. + * + * Issues with too small a value: + * - When tags are sent, a reply leaseset (~1KB) is always bundled. + * Maybe don't need to bundle more than every minute or so + * rather than every time? + * - Does the number of tags (and the threshold of 20) limit the effective + * streaming lib window size? Should the threshold and the number of + * sent tags be variable based on the message rate? + * + * We have to be very careful if we implement an adaptive scheme, + * since the key manager is per-router, not per-local-dest. + * Or maybe that's a bad idea, and we need to move to a per-dest manager. + * This needs further investigation. + * + * So a value somewhat higher than the low threshold + * seems appropriate. + */ + private static final int DEFAULT_TAGS = 40; + private static final int LOW_THRESHOLD = 20; + public static int estimateAvailableTags(RouterContext ctx, PublicKey key) { SessionKey curKey = ctx.sessionKeyManager().getCurrentKey(key); if (curKey == null) @@ -41,7 +72,7 @@ public class GarlicMessageBuilder { return buildMessage(ctx, config, new SessionKey(), new HashSet()); } public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags) { - return buildMessage(ctx, config, wrappedKey, wrappedTags, 100); + return buildMessage(ctx, config, wrappedKey, wrappedTags, DEFAULT_TAGS); } public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set wrappedTags, int numTagsToDeliver) { return buildMessage(ctx, config, wrappedKey, wrappedTags, numTagsToDeliver, false); @@ -74,13 +105,13 @@ public class GarlicMessageBuilder { if (log.shouldLog(Log.DEBUG)) log.debug("Available tags for encryption to " + key + ": " + availTags); - if (availTags < 20) { // arbitrary threshold + if (availTags < LOW_THRESHOLD) { // arbitrary threshold for (int i = 0; i < numTagsToDeliver; i++) wrappedTags.add(new SessionTag(true)); if (log.shouldLog(Log.INFO)) - log.info("Less than 20 tags are available (" + availTags + "), so we're including more"); + log.info("Too few are available (" + availTags + "), so we're including more"); } else if (ctx.sessionKeyManager().getAvailableTimeLeft(key, curKey) < 60*1000) { - // if we have > 20 tags, but they expire in under 30 seconds, we want more + // if we have enough tags, but they expire in under 30 seconds, we want more for (int i = 0; i < numTagsToDeliver; i++) wrappedTags.add(new SessionTag(true)); if (log.shouldLog(Log.INFO)) diff --git a/router/java/src/net/i2p/router/message/GarlicMessageParser.java b/router/java/src/net/i2p/router/message/GarlicMessageParser.java index 3e99e0731688dba7b279126ac3825f600ae9b5e6..84ed50b2c56baf9b41cd6642dc759d2df31bf1f9 100644 --- a/router/java/src/net/i2p/router/message/GarlicMessageParser.java +++ b/router/java/src/net/i2p/router/message/GarlicMessageParser.java @@ -9,8 +9,6 @@ package net.i2p.router.message; */ import java.util.Date; -import java.util.HashSet; -import java.util.Set; import net.i2p.data.Certificate; import net.i2p.data.DataFormatException; diff --git a/router/java/src/net/i2p/router/message/HandleGarlicMessageJob.java b/router/java/src/net/i2p/router/message/HandleGarlicMessageJob.java index a114764f6a0286e0d30aff5e5bf95c3319c03303..05aecfb89b4ab0980a81831d0023b6f6bdd56949 100644 --- a/router/java/src/net/i2p/router/message/HandleGarlicMessageJob.java +++ b/router/java/src/net/i2p/router/message/HandleGarlicMessageJob.java @@ -106,6 +106,7 @@ public class HandleGarlicMessageJob extends JobImpl implements GarlicMessageRece } } + @Override public void dropped() { getContext().messageHistory().messageProcessingError(_message.getUniqueId(), _message.getClass().getName(), diff --git a/router/java/src/net/i2p/router/message/OutboundClientMessageStatus.java b/router/java/src/net/i2p/router/message/OutboundClientMessageStatus.java index b24154d6f63ec475fdc6e60b9a045adde3608c50..3d15ce07cd6179475a405bb9990287d0430c4109 100644 --- a/router/java/src/net/i2p/router/message/OutboundClientMessageStatus.java +++ b/router/java/src/net/i2p/router/message/OutboundClientMessageStatus.java @@ -20,7 +20,7 @@ class OutboundClientMessageStatus { private ClientMessage _msg; private PayloadGarlicConfig _clove; private LeaseSet _leaseSet; - private Set _sent; + private final Set _sent; private int _numLookups; private boolean _success; private boolean _failure; @@ -114,6 +114,7 @@ class OutboundClientMessageStatus { public Hash getGateway() { return _gateway; } public TunnelId getTunnel() { return _tunnel; } + @Override public int hashCode() { int rv = 0; if (_gateway != null) @@ -123,6 +124,7 @@ class OutboundClientMessageStatus { return rv; } + @Override public boolean equals(Object o) { if (o == null) return false; if (o.getClass() != Tunnel.class) return false; diff --git a/router/java/src/net/i2p/router/message/PayloadGarlicConfig.java b/router/java/src/net/i2p/router/message/PayloadGarlicConfig.java index eb2c0488634cd8c3a88672a1bf3d12037689dafa..2b2a8f9c88741c865d0a6640bf2e0e7d6d9d45a5 100644 --- a/router/java/src/net/i2p/router/message/PayloadGarlicConfig.java +++ b/router/java/src/net/i2p/router/message/PayloadGarlicConfig.java @@ -33,6 +33,7 @@ public class PayloadGarlicConfig extends GarlicConfig { } public I2NPMessage getPayload() { return _payload; } + @Override protected String getSubData() { StringBuffer buf = new StringBuffer(); buf.append("<payloadMessage>").append(_payload).append("</payloadMessage>"); diff --git a/router/java/src/net/i2p/router/networkdb/DatabaseLookupMessageHandler.java b/router/java/src/net/i2p/router/networkdb/DatabaseLookupMessageHandler.java index db696461a8f7669e0b5b3329b915592c4887a6e4..84dd56890b3c082ac25a84062eb96cbc2bfbb859 100644 --- a/router/java/src/net/i2p/router/networkdb/DatabaseLookupMessageHandler.java +++ b/router/java/src/net/i2p/router/networkdb/DatabaseLookupMessageHandler.java @@ -28,19 +28,12 @@ public class DatabaseLookupMessageHandler implements HandlerJobBuilder { _context = context; _log = context.logManager().getLog(DatabaseLookupMessageHandler.class); _context.statManager().createRateStat("netDb.lookupsReceived", "How many netDb lookups have we received?", "NetworkDatabase", new long[] { 5*60*1000l, 60*60*1000l, 24*60*60*1000l }); + // FIXME: is netDb.lookupsDropped actually used elsewhere? _context.statManager().createRateStat("netDb.lookupsDropped", "How many netDb lookups did we drop due to throttling?", "NetworkDatabase", new long[] { 5*60*1000l, 60*60*1000l, 24*60*60*1000l }); } public Job createJob(I2NPMessage receivedMessage, RouterIdentity from, Hash fromHash) { _context.statManager().addRateData("netDb.lookupsReceived", 1, 0); - - if (true || _context.throttle().acceptNetDbLookupRequest(((DatabaseLookupMessage)receivedMessage).getSearchKey())) { - return new HandleDatabaseLookupMessageJob(_context, (DatabaseLookupMessage)receivedMessage, from, fromHash); - } else { - if (_log.shouldLog(Log.INFO)) - _log.info("Dropping lookup request as throttled"); - _context.statManager().addRateData("netDb.lookupsDropped", 1, 1); - return null; - } + return new HandleDatabaseLookupMessageJob(_context, (DatabaseLookupMessage)receivedMessage, from, fromHash); } } diff --git a/router/java/src/net/i2p/router/networkdb/HandleDatabaseLookupMessageJob.java b/router/java/src/net/i2p/router/networkdb/HandleDatabaseLookupMessageJob.java index a953bd59595d65fb7887ac690334a187c0cc2dbb..76bc897ed149d6acb7329284fad17b52417e0565 100644 --- a/router/java/src/net/i2p/router/networkdb/HandleDatabaseLookupMessageJob.java +++ b/router/java/src/net/i2p/router/networkdb/HandleDatabaseLookupMessageJob.java @@ -262,6 +262,7 @@ public class HandleDatabaseLookupMessageJob extends JobImpl { public String getName() { return "Handle Database Lookup Message"; } + @Override public void dropped() { getContext().messageHistory().messageProcessingError(_message.getUniqueId(), _message.getClass().getName(), diff --git a/router/java/src/net/i2p/router/networkdb/HandleDatabaseStoreMessageJob.java b/router/java/src/net/i2p/router/networkdb/HandleDatabaseStoreMessageJob.java index 3a395db0ace649c6a49d1c0041f0bbba6eaab899..c4a0b9f451af4ecc04515fae490be2ab43d266c4 100644 --- a/router/java/src/net/i2p/router/networkdb/HandleDatabaseStoreMessageJob.java +++ b/router/java/src/net/i2p/router/networkdb/HandleDatabaseStoreMessageJob.java @@ -132,6 +132,7 @@ public class HandleDatabaseStoreMessageJob extends JobImpl { public String getName() { return "Handle Database Store Message"; } + @Override public void dropped() { getContext().messageHistory().messageProcessingError(_message.getUniqueId(), _message.getClass().getName(), "Dropped due to overload"); } diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/ExploreJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/ExploreJob.java index 388afa8869627306fbbc7c0f47b6d1cfb720e175..e8e0a01f102212832cd5ba92f5fe17dc8cbf6476 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/ExploreJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/ExploreJob.java @@ -11,7 +11,6 @@ package net.i2p.router.networkdb.kademlia; import java.util.List; import net.i2p.data.Hash; -import net.i2p.data.RouterInfo; import net.i2p.data.TunnelId; import net.i2p.data.i2np.DatabaseLookupMessage; import net.i2p.router.RouterContext; @@ -41,11 +40,11 @@ class ExploreJob extends SearchJob { /** only send the closest "dont tell me about" refs... * Override to make this bigger because we want to include both the * floodfills and the previously-queried peers */ - static final int MAX_CLOSEST = 20; + static final int MAX_CLOSEST = 20; // LINT -- field hides another field, this isn't an override. /** Override to make this shorter, since we don't sort out the * unresponsive ff peers like we do in FloodOnlySearchJob */ - static final int PER_FLOODFILL_PEER_TIMEOUT = 5*1000; + static final int PER_FLOODFILL_PEER_TIMEOUT = 5*1000; // LINT -- field hides another field, this isn't an override. /** * Create a new search for the routingKey specified @@ -78,6 +77,7 @@ class ExploreJob extends SearchJob { * @param replyGateway gateway for the reply tunnel * @param expiration when the search should stop */ + @Override protected DatabaseLookupMessage buildMessage(TunnelId replyTunnelId, Hash replyGateway, long expiration) { DatabaseLookupMessage msg = new DatabaseLookupMessage(getContext(), true); msg.setSearchKey(getState().getTarget()); @@ -112,11 +112,13 @@ class ExploreJob extends SearchJob { * replies sent back to us directly). This uses the similar overrides as the other buildMessage above. * */ + @Override protected DatabaseLookupMessage buildMessage(long expiration) { return buildMessage(null, getContext().router().getRouterInfo().getIdentity().getHash(), expiration); } /** max # of concurrent searches */ + @Override protected int getBredth() { return EXPLORE_BREDTH; } @@ -125,6 +127,7 @@ class ExploreJob extends SearchJob { * number of peers that we didn't know about before. * */ + @Override protected void newPeersFound(int numNewPeers) { // who cares about how many new peers. well, maybe we do. but for now, // we'll do the simplest thing that could possibly work. @@ -139,5 +142,6 @@ class ExploreJob extends SearchJob { * */ + @Override public String getName() { return "Kademlia NetDb Explore"; } } diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlyLookupSelector.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlyLookupSelector.java index b8c46fc33eecf366c8b523a438e1c697c6bdc5be..ff98d1429b5233a2f29870bc9d4782d5de706b43 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlyLookupSelector.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlyLookupSelector.java @@ -3,7 +3,6 @@ package net.i2p.router.networkdb.kademlia; import net.i2p.data.i2np.DatabaseSearchReplyMessage; import net.i2p.data.i2np.DatabaseStoreMessage; import net.i2p.data.i2np.I2NPMessage; -import net.i2p.router.JobImpl; import net.i2p.router.MessageSelector; import net.i2p.router.RouterContext; import net.i2p.util.Log; diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java index 5e68863026152c5ba58561df3759bfb06fc6c6ee..e5b5e962d6b076a2bde7f651b3f8ca08aef6661f 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java @@ -8,11 +8,7 @@ import java.util.List; import net.i2p.data.Hash; import net.i2p.data.i2np.DatabaseLookupMessage; -import net.i2p.data.i2np.DatabaseSearchReplyMessage; -import net.i2p.data.i2np.DatabaseStoreMessage; -import net.i2p.data.i2np.I2NPMessage; import net.i2p.router.Job; -import net.i2p.router.JobImpl; import net.i2p.router.MessageSelector; import net.i2p.router.OutNetMessage; import net.i2p.router.ReplyJob; @@ -44,8 +40,8 @@ class FloodOnlySearchJob extends FloodSearchJob { protected Log _log; private FloodfillNetworkDatabaseFacade _facade; protected Hash _key; - private List _onFind; - private List _onFailed; + private final List _onFind; + private final List _onFailed; private long _expiration; protected int _timeoutMs; private long _origExpiration; @@ -54,9 +50,9 @@ class FloodOnlySearchJob extends FloodSearchJob { private volatile boolean _dead; private long _created; private boolean _shouldProcessDSRM; - private HashSet _unheardFrom; + private final HashSet _unheardFrom; - protected List _out; + protected final List _out; protected MessageSelector _replySelector; protected ReplyJob _onReply; protected Job _onTimeout; @@ -83,6 +79,7 @@ class FloodOnlySearchJob extends FloodSearchJob { _created = System.currentTimeMillis(); _shouldProcessDSRM = false; } + @Override void addDeferred(Job onFind, Job onFailed, long timeoutMs, boolean isLease) { if (_dead) { getContext().jobQueue().addJob(onFailed); @@ -91,10 +88,12 @@ class FloodOnlySearchJob extends FloodSearchJob { if (onFailed != null) synchronized (_onFailed) { _onFailed.add(onFailed); } } } + @Override public long getExpiration() { return _expiration; } public long getCreated() { return _created; } public boolean shouldProcessDSRM() { return _shouldProcessDSRM; } private static final int CONCURRENT_SEARCHES = 2; + @Override public void runJob() { // pick some floodfill peers and send out the searches List floodfillPeers = _facade.getFloodfillPeers(); @@ -184,10 +183,14 @@ class FloodOnlySearchJob extends FloodSearchJob { failed(); } } + @Override public String getName() { return "NetDb flood search (phase 1)"; } + @Override Hash getKey() { return _key; } + @Override void decrementRemaining() { if (_lookupsRemaining > 0) _lookupsRemaining--; } + @Override int getLookupsRemaining() { return _lookupsRemaining; } /** Note that we heard from the peer */ void decrementRemaining(Hash peer) { @@ -197,6 +200,7 @@ class FloodOnlySearchJob extends FloodSearchJob { } } + @Override void failed() { synchronized (this) { if (_dead) return; @@ -224,6 +228,7 @@ class FloodOnlySearchJob extends FloodSearchJob { } } } + @Override void success() { synchronized (this) { if (_dead) return; diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java index 575de5e7b356fc37e94ff5f77660576d0490900a..3772b18d1ee2694f0e542ac20f2b462d73c3cc4f 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java @@ -31,7 +31,7 @@ import net.i2p.util.Log; */ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacade { public static final char CAPACITY_FLOODFILL = 'f'; - private Map _activeFloodQueries; + private final Map _activeFloodQueries; private boolean _floodfillEnabled; /** for testing, see isFloodfill() below */ private static String _alwaysQuery; @@ -55,11 +55,13 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad _context.statManager().createRateStat("netDb.republishQuantity", "How many peers do we need to send a found leaseSet to?", "NetworkDatabase", new long[] { 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l }); } + @Override public void startup() { super.startup(); _context.jobQueue().addJob(new FloodfillMonitorJob(_context, this)); } + @Override protected void createHandlers() { _context.inNetMessagePool().registerHandlerJobBuilder(DatabaseLookupMessage.MESSAGE_TYPE, new FloodfillDatabaseLookupMessageHandler(_context)); _context.inNetMessagePool().registerHandlerJobBuilder(DatabaseStoreMessage.MESSAGE_TYPE, new FloodfillDatabaseStoreMessageHandler(_context, this)); @@ -70,6 +72,7 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad /** * @throws IllegalArgumentException if the local router info is invalid */ + @Override public void publish(RouterInfo localRouterInfo) throws IllegalArgumentException { if (localRouterInfo == null) throw new IllegalArgumentException("wtf, null localRouterInfo?"); if (_context.router().isHidden()) return; // DE-nied! @@ -77,6 +80,7 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad sendStore(localRouterInfo.getIdentity().calculateHash(), localRouterInfo, null, null, PUBLISH_TIMEOUT, null); } + @Override public void sendStore(Hash key, DataStructure ds, Job onSuccess, Job onFailure, long sendTimeout, Set toIgnore) { // if we are a part of the floodfill netDb, don't send out our own leaseSets as part // of the flooding - instead, send them to a random floodfill peer so *they* can flood 'em out. @@ -131,6 +135,7 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad private static final int FLOOD_PRIORITY = 200; private static final int FLOOD_TIMEOUT = 30*1000; + @Override protected PeerSelector createPeerSelector() { return new FloodfillPeerSelector(_context); } public void setFloodfillEnabled(boolean yes) { _floodfillEnabled = yes; } @@ -183,6 +188,7 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad * without any match) * */ + @Override SearchJob search(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs, boolean isLease) { //if (true) return super.search(key, onFindJob, onFailedLookupJob, timeoutMs, isLease); if (key == null) throw new IllegalArgumentException("searchin for nothin, eh?"); @@ -282,6 +288,7 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad * Search for a newer router info, drop it from the db if the search fails, * unless just started up or have bigger problems. */ + @Override protected void lookupBeforeDropping(Hash peer, RouterInfo info) { // following are some special situations, we don't want to // drop the peer in these cases @@ -356,8 +363,8 @@ class FloodSearchJob extends JobImpl { private Log _log; private FloodfillNetworkDatabaseFacade _facade; private Hash _key; - private List _onFind; - private List _onFailed; + private final List _onFind; + private final List _onFailed; private long _expiration; private int _timeoutMs; private long _origExpiration; diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java index 7504e660a02070e18b284bc779709b9ddbcf73b9..049140397fc4127a8cbe7adc501a2475ea89f68e 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillPeerSelector.java @@ -31,10 +31,12 @@ class FloodfillPeerSelector extends PeerSelector { * * @return List of Hash for the peers selected */ + @Override public List selectMostReliablePeers(Hash key, int maxNumRouters, Set peersToIgnore, KBucketSet kbuckets) { return selectNearestExplicitThin(key, maxNumRouters, peersToIgnore, kbuckets, true); } + @Override public List selectNearestExplicitThin(Hash key, int maxNumRouters, Set peersToIgnore, KBucketSet kbuckets) { return selectNearestExplicitThin(key, maxNumRouters, peersToIgnore, kbuckets, false); } diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillStoreJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillStoreJob.java index f3880597d8334de33014b199d9758255dcb311f4..7c37cfc18ee1ab1d8d189a7138a12889233ef5aa 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillStoreJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillStoreJob.java @@ -34,17 +34,21 @@ class FloodfillStoreJob extends StoreJob { _facade = facade; } + @Override protected int getParallelization() { return 1; } + @Override protected int getRedundancy() { return 1; } /** * Send was totally successful */ + @Override protected void succeed() { super.succeed(); if (_state != null) getContext().jobQueue().addJob(new FloodfillVerifyStoreJob(getContext(), _state.getTarget(), _facade)); } + @Override public String getName() { return "Floodfill netDb store"; } } \ No newline at end of file diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/HandleFloodfillDatabaseLookupMessageJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/HandleFloodfillDatabaseLookupMessageJob.java index e3a6b6df9d372192c2118b1c5c63440a01d446aa..f8c7adf42492e52ad45f3393bf30531003cbd8ae 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/HandleFloodfillDatabaseLookupMessageJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/HandleFloodfillDatabaseLookupMessageJob.java @@ -30,6 +30,7 @@ public class HandleFloodfillDatabaseLookupMessageJob extends HandleDatabaseLooku super(ctx, receivedMessage, from, fromHash); } + @Override protected boolean answerAllQueries() { if (!FloodfillNetworkDatabaseFacade.floodfillEnabled(getContext())) return false; return FloodfillNetworkDatabaseFacade.isFloodfill(getContext().router().getRouterInfo()); @@ -40,6 +41,7 @@ public class HandleFloodfillDatabaseLookupMessageJob extends HandleDatabaseLooku * This gets the word out to routers that we are no longer floodfill, so they * will stop bugging us. */ + @Override protected void sendClosest(Hash key, Set routerInfoSet, Hash toPeer, TunnelId replyTunnel) { super.sendClosest(key, routerInfoSet, toPeer, replyTunnel); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/HandleFloodfillDatabaseStoreMessageJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/HandleFloodfillDatabaseStoreMessageJob.java index 1b00a1b251373fdc084e0357b2c3173491951327..505638ecbdb31246eec5110d01c4d80c5cc9a8a4 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/HandleFloodfillDatabaseStoreMessageJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/HandleFloodfillDatabaseStoreMessageJob.java @@ -184,6 +184,7 @@ public class HandleFloodfillDatabaseStoreMessageJob extends JobImpl { public String getName() { return "Handle Database Store Message"; } + @Override public void dropped() { getContext().messageHistory().messageProcessingError(_message.getUniqueId(), _message.getClass().getName(), "Dropped due to overload"); } diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KBucketImpl.java b/router/java/src/net/i2p/router/networkdb/kademlia/KBucketImpl.java index 5d8e186f50728db534008019467733dab36e6705..c6668a41e4fcefd5527dce2c5f0682228202cb2e 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/KBucketImpl.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/KBucketImpl.java @@ -26,7 +26,7 @@ import net.i2p.util.RandomSource; class KBucketImpl implements KBucket { private Log _log; /** set of Hash objects for the peers in the kbucket */ - private List _entries; + private final List _entries; /** we center the kbucket set on the given hash, and derive distances from this */ private Hash _local; /** include if any bits equal or higher to this bit (in big endian order) */ @@ -328,6 +328,7 @@ class KBucketImpl implements KBucket { return BigInteger.ZERO.setBit(_begin); } + @Override public String toString() { StringBuffer buf = new StringBuffer(1024); buf.append("KBucketImpl: "); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KBucketSet.java b/router/java/src/net/i2p/router/networkdb/kademlia/KBucketSet.java index 6b3ca79d6c3544a63139ce72fa673b820ea38c61..ddbfb06f7f176a35a51fb976aafa8877c32426f2 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/KBucketSet.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/KBucketSet.java @@ -138,6 +138,7 @@ class KBucketSet { _log.info(toString()); } + @Override public String toString() { BigInteger us = new BigInteger(1, _us.getData()); StringBuffer buf = new StringBuffer(1024); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java index 6ff82c6a415f66aeab9dabb9dfb3892f37106f61..28a35862be102f5cbe5996f570691d555379cb6a 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java @@ -53,7 +53,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { private DataStore _ds; // hash to DataStructure mapping, persisted when necessary /** where the data store is pushing the data */ private String _dbDir; - private Set _exploreKeys; // set of Hash objects that we should search on (to fill up a bucket, not to get data) + private final Set _exploreKeys = new HashSet(64); // set of Hash objects that we should search on (to fill up a bucket, not to get data) private boolean _initialized; /** Clock independent time of when we started up */ private long _started; @@ -69,7 +69,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { * removed when the job decides to stop running. * */ - private Map _publishingLeaseSets; + private final Map _publishingLeaseSets; /** * Hash of the key currently being searched for, pointing the SearchJob that @@ -77,7 +77,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { * added on to the list of jobs fired on success/failure * */ - private Map _activeRequests; + private final Map _activeRequests; /** * The search for the given key is no longer active @@ -115,11 +115,13 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { protected final static int MIN_REMAINING_ROUTERS = 25; /** - * dont accept any dbDtore of a router over 24 hours old (unless we dont - * know anyone or just started up) + * limits for accepting a dbDtore of a router (unless we dont + * know anyone or just started up) -- see validate() below */ private final static long ROUTER_INFO_EXPIRATION = 3*24*60*60*1000l; + private final static long ROUTER_INFO_EXPIRATION_MIN = 3*60*60*1000l; private final static long ROUTER_INFO_EXPIRATION_SHORT = 90*60*1000l; + private final static long ROUTER_INFO_EXPIRATION_FLOODFILL = 60*60*1000l; private final static long EXPLORE_JOB_DELAY = 10*60*1000l; private final static long PUBLISH_JOB_DELAY = 5*60*1000l; @@ -176,7 +178,8 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { _initialized = false; _kb = null; _ds = null; - _exploreKeys = null; + _exploreKeys.clear(); // hope this doesn't cause an explosion, it shouldn't. + // _exploreKeys = null; } public void restart() { @@ -218,7 +221,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { _kb = new KBucketSet(_context, ri.getIdentity().getHash()); _ds = new PersistentDataStore(_context, dbDir, this); //_ds = new TransientDataStore(); - _exploreKeys = new HashSet(64); +// _exploreKeys = new HashSet(64); _dbDir = dbDir; createHandlers(); @@ -331,6 +334,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { return rv; } + @Override public int getKnownRouters() { if (_kb == null) return 0; CountRouters count = new CountRouters(); @@ -349,11 +353,13 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { } } + @Override public int getKnownLeaseSets() { if (_ds == null) return 0; return _ds.countLeaseSets(); } - + + /* aparently, not used?? should be public if used elsewhere. */ private class CountLeaseSets implements SelectionCollector { private int _count; public int size() { return _count; } @@ -364,7 +370,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { _count++; } } - + /** * This is fast and doesn't use synchronization, * but it includes both routerinfos and leasesets. @@ -566,7 +572,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { _log.error("LeaseSet to expire too far in the future: " + leaseSet.getDestination().calculateHash().toBase64() + " expires on " + new Date(leaseSet.getEarliestLeaseDate()), new Exception("Rejecting store")); - return "Expired leaseSet for " + leaseSet.getDestination().calculateHash().toBase64() + return "Future expiring leaseSet for " + leaseSet.getDestination().calculateHash().toBase64() + " expiring in " + DataHelper.formatDuration(age); } return null; @@ -620,7 +626,22 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { */ String validate(Hash key, RouterInfo routerInfo) throws IllegalArgumentException { long now = _context.clock().now(); - + boolean upLongEnough = _context.router().getUptime() > 60*60*1000; + // Once we're over 300 routers, reduce the expiration time down from the default, + // as a crude way of limiting memory usage. + // i.e. at 600 routers the expiration time will be about half the default, etc. + // And if we're floodfill, we can keep the expiration really short, since + // we are always getting the latest published to us. + // As the net grows this won't be sufficient, and we'll have to implement + // flushing some from memory, while keeping all on disk. + long adjustedExpiration; + if (FloodfillNetworkDatabaseFacade.floodfillEnabled(_context)) + adjustedExpiration = ROUTER_INFO_EXPIRATION_FLOODFILL; + else + adjustedExpiration = Math.min(ROUTER_INFO_EXPIRATION, + ROUTER_INFO_EXPIRATION_MIN + + ((ROUTER_INFO_EXPIRATION - ROUTER_INFO_EXPIRATION_MIN) * 300 / (_kb.size() + 1))); + if (!key.equals(routerInfo.getIdentity().getHash())) { if (_log.shouldLog(Log.WARN)) _log.warn("Invalid store attempt! key does not match routerInfo.identity! key = " + key + ", router = " + routerInfo); @@ -629,7 +650,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { if (_log.shouldLog(Log.WARN)) _log.warn("Invalid routerInfo signature! forged router structure! router = " + routerInfo); return "Invalid routerInfo signature on " + key.toBase64(); - } else if (!routerInfo.isCurrent(ROUTER_INFO_EXPIRATION) && (_context.router().getUptime() > 60*60*1000) ) { + } else if (upLongEnough && !routerInfo.isCurrent(adjustedExpiration)) { if (routerInfo.getNetworkId() != Router.NETWORK_ID) { _context.shitlist().shitlistRouter(key, "Peer is not in our network"); return "Peer is not in our network (" + routerInfo.getNetworkId() + ", wants " @@ -657,10 +678,10 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { String rv = "Peer " + key.toBase64() + " is from another network, not accepting it (id=" + routerInfo.getNetworkId() + ", want " + Router.NETWORK_ID + ")"; return rv; - } else if ( (_context.router().getUptime() > 60*60*1000) && (routerInfo.getPublished() < now - 2*24*60*60*1000l) ) { + } else if (upLongEnough && (routerInfo.getPublished() < now - 2*24*60*60*1000l) ) { long age = _context.clock().now() - routerInfo.getPublished(); return "Peer " + key.toBase64() + " published " + DataHelper.formatDuration(age) + " ago"; - } else if (!routerInfo.isCurrent(ROUTER_INFO_EXPIRATION_SHORT) && (_context.router().getUptime() > 60*60*1000) ) { + } else if (upLongEnough && !routerInfo.isCurrent(ROUTER_INFO_EXPIRATION_SHORT)) { if (routerInfo.getAddresses().size() <= 0) return "Peer " + key.toBase64() + " published > 90m ago with no addresses"; RouterAddress ra = routerInfo.getTargetAddress("SSU"); @@ -868,6 +889,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { } } + @Override public void renderRouterInfoHTML(Writer out, String routerPrefix) throws IOException { StringBuffer buf = new StringBuffer(4*1024); buf.append("<h2>Network Database RouterInfo Lookup</h2>\n"); @@ -895,23 +917,14 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { renderStatusHTML(out, true); } - public void renderStatusHTML(Writer out, boolean full) throws IOException { - int size = getKnownRouters() * 512; - if (full) - size *= 4; - StringBuffer buf = new StringBuffer(size); + @Override + public void renderLeaseSetHTML(Writer out) throws IOException { + StringBuffer buf = new StringBuffer(4*1024); buf.append("<h2>Network Database Contents</h2>\n"); - if (!_initialized) { - buf.append("<i>Not initialized</i>\n"); - out.write(buf.toString()); - out.flush(); - return; - } + buf.append("<a href=\"netdb.jsp\">View RouterInfo</a>"); + buf.append("<h3>LeaseSets</h3>\n"); Set leases = new TreeSet(new LeaseSetComparator()); leases.addAll(getLeases()); - buf.append("<h3>Leases</h3>\n"); - out.write(buf.toString()); - buf.setLength(0); long now = _context.clock().now(); for (Iterator iter = leases.iterator(); iter.hasNext(); ) { LeaseSet ls = (LeaseSet)iter.next(); @@ -951,7 +964,25 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { out.write(buf.toString()); buf.setLength(0); } + out.write(buf.toString()); + out.flush(); + } + + @Override + public void renderStatusHTML(Writer out, boolean full) throws IOException { + int size = getKnownRouters() * 512; + if (full) + size *= 4; + StringBuffer buf = new StringBuffer(size); + out.write("<h2>Network Database Contents</h2>\n"); + if (!_initialized) { + buf.append("<i>Not initialized</i>\n"); + out.write(buf.toString()); + out.flush(); + return; + } + out.write("<a href=\"netdb.jsp?l=1\">View LeaseSets</a>"); Hash us = _context.routerHash(); out.write("<a name=\"routers\" /><h3>Routers (<a href=\"netdb.jsp"); if (full) diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/PeerSelector.java b/router/java/src/net/i2p/router/networkdb/kademlia/PeerSelector.java index 26c1799a36e044655d21915d293eb694802b66fd..c88897a127031dcc818d5d5302ca5ef1e19cdaaa 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/PeerSelector.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/PeerSelector.java @@ -42,7 +42,7 @@ public class PeerSelector { * * @return ordered list of Hash objects */ - public List selectMostReliablePeers(Hash key, int numClosest, Set alreadyChecked, KBucketSet kbuckets) { + public List selectMostReliablePeers(Hash key, int numClosest, Set alreadyChecked, KBucketSet kbuckets) {// LINT -- Exporting non-public type through public API // get the peers closest to the key List nearest = selectNearestExplicit(key, numClosest, alreadyChecked, kbuckets); return nearest; @@ -55,7 +55,7 @@ public class PeerSelector { * * @return List of Hash for the peers selected, ordered by bucket (but intra bucket order is not defined) */ - public List selectNearestExplicit(Hash key, int maxNumRouters, Set peersToIgnore, KBucketSet kbuckets) { + public List selectNearestExplicit(Hash key, int maxNumRouters, Set peersToIgnore, KBucketSet kbuckets) {// LINT -- Exporting non-public type through public API if (true) return selectNearestExplicitThin(key, maxNumRouters, peersToIgnore, kbuckets); @@ -91,7 +91,7 @@ public class PeerSelector { * * @return List of Hash for the peers selected, ordered by bucket (but intra bucket order is not defined) */ - public List selectNearestExplicitThin(Hash key, int maxNumRouters, Set peersToIgnore, KBucketSet kbuckets) { + public List selectNearestExplicitThin(Hash key, int maxNumRouters, Set peersToIgnore, KBucketSet kbuckets) { // LINT -- Exporting non-public type through public API if (peersToIgnore == null) peersToIgnore = new HashSet(1); peersToIgnore.add(_context.router().getRouterInfo().getIdentity().getHash()); @@ -195,7 +195,7 @@ public class PeerSelector { * * @return List of Hash for the peers selected, ordered by bucket (but intra bucket order is not defined) */ - public List selectNearest(Hash key, int maxNumRouters, Set peersToIgnore, KBucketSet kbuckets) { + public List selectNearest(Hash key, int maxNumRouters, Set peersToIgnore, KBucketSet kbuckets) { // LINT -- Exporting non-public type through public API // sure, this may not be exactly correct per kademlia (peers on the border of a kbucket in strict kademlia // would behave differently) but I can see no reason to keep around an /additional/ more complicated algorithm. // later if/when selectNearestExplicit gets costly, we may revisit this (since kbuckets let us cache the distance() diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/PersistentDataStore.java b/router/java/src/net/i2p/router/networkdb/kademlia/PersistentDataStore.java index 5d0d219dbe6fe125bbb698d0bcb49724f783b114..0186bd922529992315586b6649f40c1be397d5f3 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/PersistentDataStore.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/PersistentDataStore.java @@ -56,15 +56,18 @@ class PersistentDataStore extends TransientDataStore { writer.start(); } + @Override public void restart() { _dbDir = _facade.getDbDir(); } + @Override public DataStructure remove(Hash key) { _context.jobQueue().addJob(new RemoveJob(key)); return super.remove(key); } + @Override public void put(Hash key, DataStructure data) { if ( (data == null) || (key == null) ) return; super.put(key, data); @@ -105,7 +108,7 @@ class PersistentDataStore extends TransientDataStore { * Queue up writes, write up to 600 files every 10 minutes */ private class Writer implements Runnable { - private Map _keys; + private final Map _keys; private List _keyOrder; public Writer() { _keys = new HashMap(64); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/RepublishLeaseSetJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/RepublishLeaseSetJob.java index ac191a96c745d7495c77371a543828bde144d703..95af13a4322fa493abc30a702f592a76e946bfd8 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/RepublishLeaseSetJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/RepublishLeaseSetJob.java @@ -23,7 +23,7 @@ import net.i2p.util.Log; public class RepublishLeaseSetJob extends JobImpl { private Log _log; private final static long REPUBLISH_LEASESET_DELAY = 5*60*1000; - public final static long REPUBLISH_LEASESET_TIMEOUT = 60*1000; + public final /* static */ long REPUBLISH_LEASESET_TIMEOUT = 60*1000; private Hash _dest; private KademliaNetworkDatabaseFacade _facade; /** this is actually last attempted publish */ diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/SearchJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/SearchJob.java index 868c6b1084cc7c776e60e1a7d12fbb937511ea63..161f2900128e32e9c6c92a9675535b2445a7ab95 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/SearchJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/SearchJob.java @@ -47,7 +47,7 @@ class SearchJob extends JobImpl { private boolean _isLease; private Job _pendingRequeueJob; private PeerSelector _peerSelector; - private List _deferredSearches; + private final List _deferredSearches; private boolean _deferredCleared; private long _startedOn; private boolean _floodfillPeersExhausted; @@ -780,6 +780,7 @@ class SearchJob extends JobImpl { public String getName() { return "Kademlia NetDb Search"; } + @Override public String toString() { return super.toString() + " started " + DataHelper.formatDuration((getContext().clock().now() - _startedOn)) + " ago"; diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/SearchMessageSelector.java b/router/java/src/net/i2p/router/networkdb/kademlia/SearchMessageSelector.java index 4f3869072fef05e5568bea99325e6f7f0c131461..73b3ddf24ece64c6c882e342a5e12abe5ea08a7b 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/SearchMessageSelector.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/SearchMessageSelector.java @@ -36,6 +36,7 @@ class SearchMessageSelector implements MessageSelector { _log.debug("[" + _id + "] Created: " + toString()); } + @Override public String toString() { return "Search selector [" + _id + "] looking for a reply from " + _peer + " with regards to " + _state.getTarget(); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/SearchState.java b/router/java/src/net/i2p/router/networkdb/kademlia/SearchState.java index da00483ab4cca89f05d8679c0ba24ca698010da4..a12f58fd74e5f377f5a620ae7b15dc72eb589ec8 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/SearchState.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/SearchState.java @@ -17,12 +17,12 @@ import net.i2p.router.RouterContext; */ class SearchState { private RouterContext _context; - private HashSet _pendingPeers; + private final HashSet _pendingPeers; private HashMap _pendingPeerTimes; - private HashSet _attemptedPeers; - private HashSet _failedPeers; - private HashSet _successfulPeers; - private HashSet _repliedPeers; + private final HashSet _attemptedPeers; + private final HashSet _failedPeers; + private final HashSet _successfulPeers; + private final HashSet _repliedPeers; private Hash _searchKey; private volatile long _completed; private volatile long _started; @@ -166,6 +166,7 @@ class SearchState { } } + @Override public String toString() { StringBuffer buf = new StringBuffer(256); buf.append("Searching for ").append(_searchKey); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/SingleSearchJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/SingleSearchJob.java index 3ec005ec5ede2de0629d45ad2624468b83ae2435..74c75cb5a3a5fead94240739b3cfdc31d540b463 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/SingleSearchJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/SingleSearchJob.java @@ -2,7 +2,6 @@ package net.i2p.router.networkdb.kademlia; import net.i2p.data.Hash; import net.i2p.data.i2np.DatabaseLookupMessage; -import net.i2p.router.JobImpl; import net.i2p.router.RouterContext; import net.i2p.router.OutNetMessage; import net.i2p.router.TunnelInfo; @@ -23,8 +22,11 @@ class SingleSearchJob extends FloodOnlySearchJob { super(ctx, null, key, null, null, 5*1000, false); _to = to; } + @Override public String getName() { return "NetDb search key from DSRM"; } + @Override public boolean shouldProcessDSRM() { return false; } // don't loop + @Override public void runJob() { _onm = getContext().messageRegistry().registerPending(_replySelector, _onReply, _onTimeout, _timeoutMs); DatabaseLookupMessage dlm = new DatabaseLookupMessage(getContext(), true); @@ -44,8 +46,10 @@ class SingleSearchJob extends FloodOnlySearchJob { getContext().tunnelDispatcher().dispatchOutbound(dlm, outTunnel.getSendTunnelId(0), _to); _lookupsRemaining = 1; } + @Override void failed() { getContext().messageRegistry().unregisterPending(_onm); } + @Override void success() {} } diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/StoreMessageSelector.java b/router/java/src/net/i2p/router/networkdb/kademlia/StoreMessageSelector.java index 26d4fda1317a9770f9fca79f94521c18efe91fa1..e8f0eca7ea290d66d5e21ee10a1ea1db2f9e34d2 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/StoreMessageSelector.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/StoreMessageSelector.java @@ -55,6 +55,7 @@ class StoreMessageSelector implements MessageSelector { } } + @Override public String toString() { StringBuffer rv = new StringBuffer(64); rv.append("Waiting for netDb confirm from ").append(_peer.toBase64()).append(", found? "); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/StoreState.java b/router/java/src/net/i2p/router/networkdb/kademlia/StoreState.java index e7bfe3292620ee119396511f88ca1344839ee8fe..184c337a9bc587436a37842ea35b2be1ad273514 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/StoreState.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/StoreState.java @@ -15,12 +15,12 @@ class StoreState { private RouterContext _context; private Hash _key; private DataStructure _data; - private HashSet _pendingPeers; + private final HashSet _pendingPeers; private HashMap _pendingPeerTimes; - private HashSet _successfulPeers; - private HashSet _successfulExploratoryPeers; - private HashSet _failedPeers; - private HashSet _attemptedPeers; + private final HashSet _successfulPeers; + private final HashSet _successfulExploratoryPeers; + private final HashSet _failedPeers; + private final HashSet _attemptedPeers; private int _completeCount; private volatile long _completed; private volatile long _started; @@ -147,6 +147,7 @@ class StoreState { } } + @Override public String toString() { StringBuffer buf = new StringBuffer(256); buf.append("Storing ").append(_key); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/TransientDataStore.java b/router/java/src/net/i2p/router/networkdb/kademlia/TransientDataStore.java index d2114146827258c172ed19cf1a8f9f838795317b..5fd28cebff279c4336ece63f39dc1c1fa49d2490 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/TransientDataStore.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/TransientDataStore.java @@ -10,9 +10,7 @@ package net.i2p.router.networkdb.kademlia; import java.util.Date; import java.util.concurrent.ConcurrentHashMap; -import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -119,14 +117,17 @@ class TransientDataStore implements DataStore { } } + @Override public int hashCode() { return DataHelper.hashCode(_data); } + @Override public boolean equals(Object obj) { if ( (obj == null) || (obj.getClass() != getClass()) ) return false; TransientDataStore ds = (TransientDataStore)obj; return DataHelper.eq(ds._data, _data); } + @Override public String toString() { StringBuffer buf = new StringBuffer(); buf.append("Transient DataStore: ").append(_data.size()).append("\nKeys: "); diff --git a/router/java/src/net/i2p/router/peermanager/CapacityCalculator.java b/router/java/src/net/i2p/router/peermanager/CapacityCalculator.java index 87d13c16e2f03e65aab4920d29d0cf1b80400538..a1b9d7c2b14dc98503722452b618fe94f00e9185 100644 --- a/router/java/src/net/i2p/router/peermanager/CapacityCalculator.java +++ b/router/java/src/net/i2p/router/peermanager/CapacityCalculator.java @@ -44,6 +44,7 @@ public class CapacityCalculator extends Calculator { /** the calculator estimates over a 1 hour period */ private static long ESTIMATE_PERIOD = 60*60*1000; + @Override public double calc(PeerProfile profile) { RateStat acceptStat = profile.getTunnelCreateResponseTime(); RateStat rejectStat = profile.getTunnelHistory().getRejectionRate(); diff --git a/router/java/src/net/i2p/router/peermanager/IntegrationCalculator.java b/router/java/src/net/i2p/router/peermanager/IntegrationCalculator.java index 26aa2b911b1da99ca0f316bc1e7ee62408018a0f..7fdc5fbce21aed41be4a5181fb74f0221aabba66 100644 --- a/router/java/src/net/i2p/router/peermanager/IntegrationCalculator.java +++ b/router/java/src/net/i2p/router/peermanager/IntegrationCalculator.java @@ -17,6 +17,7 @@ public class IntegrationCalculator extends Calculator { _log = context.logManager().getLog(IntegrationCalculator.class); } + @Override public double calc(PeerProfile profile) { // give more weight to recent counts long val = profile.getDbIntroduction().getRate(24*60*60*1000l).getCurrentEventCount(); diff --git a/router/java/src/net/i2p/router/peermanager/PeerManager.java b/router/java/src/net/i2p/router/peermanager/PeerManager.java index 1c265ee6768e49bb6f22fffb7f54000d26f144fc..146e6a3f9b05e7622a605d1bb970f9d9225205f2 100644 --- a/router/java/src/net/i2p/router/peermanager/PeerManager.java +++ b/router/java/src/net/i2p/router/peermanager/PeerManager.java @@ -37,7 +37,7 @@ class PeerManager { private ProfileOrganizer _organizer; private ProfilePersistenceHelper _persistenceHelper; private List _peersByCapability[]; - private Map _capabilitiesByPeer; + private final Map _capabilitiesByPeer; public PeerManager(RouterContext context) { _context = context; diff --git a/router/java/src/net/i2p/router/peermanager/PeerProfile.java b/router/java/src/net/i2p/router/peermanager/PeerProfile.java index 2f311b52f90f0cdbeb30b1c937b9b2149180b2b0..ec05f69f61e09e5f881ec8adf7b9f79f6a546179 100644 --- a/router/java/src/net/i2p/router/peermanager/PeerProfile.java +++ b/router/java/src/net/i2p/router/peermanager/PeerProfile.java @@ -445,7 +445,9 @@ public class PeerProfile { private boolean calculateIsFailing() { return false; } void setIsFailing(boolean val) { _isFailing = val; } + @Override public int hashCode() { return (_peer == null ? 0 : _peer.hashCode()); } + @Override public boolean equals(Object obj) { if (obj == null) return false; if (obj.getClass() != PeerProfile.class) return false; @@ -453,6 +455,7 @@ public class PeerProfile { PeerProfile prof = (PeerProfile)obj; return _peer.equals(prof.getPeer()); } + @Override public String toString() { return "Profile: " + getPeer().toBase64(); } /** diff --git a/router/java/src/net/i2p/router/peermanager/PeerTestJob.java b/router/java/src/net/i2p/router/peermanager/PeerTestJob.java index 6c7aef92721b024bdde34485753d04eabaf5ccbc..c4ba39db59447f63971753d99313809c25e5419c 100644 --- a/router/java/src/net/i2p/router/peermanager/PeerTestJob.java +++ b/router/java/src/net/i2p/router/peermanager/PeerTestJob.java @@ -50,7 +50,7 @@ public class PeerTestJob extends JobImpl { /** number of peers to test each round */ private int getTestConcurrency() { return 1; } - public void startTesting(PeerManager manager) { + public void startTesting(PeerManager manager) { // LINT -- Exporting non-public type through public API _manager = manager; _keepTesting = true; getContext().jobQueue().addJob(this); @@ -222,6 +222,7 @@ public class PeerTestJob extends JobImpl { return false; } public boolean matchFound() { return _matchFound; } + @Override public String toString() { StringBuffer buf = new StringBuffer(64); buf.append("Test peer ").append(_peer.toBase64().substring(0,4)); diff --git a/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java b/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java index 1a42a244c6c1a459c19fbda3cdff133ec430ce01..906df20368d1e6700f196450a7fd911b0a43bf6a 100644 --- a/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java +++ b/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java @@ -19,6 +19,8 @@ import java.util.Properties; import java.util.Random; import java.util.Set; import java.util.TreeSet; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantReadWriteLock; import net.i2p.data.Hash; import net.i2p.data.RouterAddress; @@ -40,17 +42,17 @@ public class ProfileOrganizer { private Log _log; private RouterContext _context; /** H(routerIdentity) to PeerProfile for all peers that are fast and high capacity*/ - private Map _fastPeers; + private Map<Hash, PeerProfile> _fastPeers; /** H(routerIdentity) to PeerProfile for all peers that have high capacities */ - private Map _highCapacityPeers; + private Map<Hash, PeerProfile> _highCapacityPeers; /** H(routerIdentity) to PeerProfile for all peers that well integrated into the network and not failing horribly */ - private Map _wellIntegratedPeers; + private Map<Hash, PeerProfile> _wellIntegratedPeers; /** H(routerIdentity) to PeerProfile for all peers that are not failing horribly */ - private Map _notFailingPeers; + private Map<Hash, PeerProfile> _notFailingPeers; /** H(routerIdnetity), containing elements in _notFailingPeers */ - private List _notFailingPeersList; + private List<Hash> _notFailingPeersList; /** H(routerIdentity) to PeerProfile for all peers that ARE failing horribly (but that we haven't dropped reference to yet) */ - private Map _failingPeers; + private Map<Hash, PeerProfile> _failingPeers; /** who are we? */ private Hash _us; private ProfilePersistenceHelper _persistenceHelper; @@ -84,7 +86,7 @@ public class ProfileOrganizer { public static final int DEFAULT_MINIMUM_HIGH_CAPACITY_PEERS = 10; /** synchronized against this lock when updating the tier that peers are located in (and when fetching them from a peer) */ - private Object _reorganizeLock = new Object(); + private final ReentrantReadWriteLock _reorganizeLock = new ReentrantReadWriteLock(true); /** incredibly weak PRNG, just used for shuffling peers. no need to waste the real PRNG on this */ private Random _random = new Random(); @@ -112,6 +114,29 @@ public class ProfileOrganizer { _context.statManager().createRateStat("peer.profileReorgTime", "How long the reorg takes overall", "Peers", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); } + private void getReadLock() { + _reorganizeLock.readLock().lock(); + } + + private void releaseReadLock() { + _reorganizeLock.readLock().unlock(); + } + + /** @return true if the lock was acquired */ + private boolean getWriteLock() { + try { + boolean rv = _reorganizeLock.writeLock().tryLock(5000, TimeUnit.MILLISECONDS); + if (!rv) + _log.error("no lock, size is: " + _reorganizeLock.getQueueLength(), new Exception("rats")); + return rv; + } catch (InterruptedException ie) {} + return false; + } + + private void releaseWriteLock() { + _reorganizeLock.writeLock().unlock(); + } + public void setUs(Hash us) { _us = us; } Hash getUs() { return _us; } @@ -124,42 +149,52 @@ public class ProfileOrganizer { * */ public PeerProfile getProfile(Hash peer) { - synchronized (_reorganizeLock) { + getReadLock(); + try { return locked_getProfile(peer); - } + } finally { releaseReadLock(); } } /** * Add the new profile, returning the old value (or null if no profile existed) * */ - public PeerProfile addProfile(PeerProfile profile) throws IllegalStateException { + public PeerProfile addProfile(PeerProfile profile) { if ( (profile == null) || (profile.getPeer() == null) ) return null; if (_log.shouldLog(Log.DEBUG)) _log.debug("New profile created for " + profile.getPeer().toBase64()); - synchronized (_reorganizeLock) { - PeerProfile old = locked_getProfile(profile.getPeer()); - profile.coalesceStats(); + PeerProfile old = getProfile(profile.getPeer()); + profile.coalesceStats(); + if (!getWriteLock()) + return old; + try { locked_placeProfile(profile); _strictCapacityOrder.add(profile); - return old; - } + } finally { releaseWriteLock(); } + return old; } - public int countFastPeers() { synchronized (_reorganizeLock) { return _fastPeers.size(); } } - public int countHighCapacityPeers() { synchronized (_reorganizeLock) { return _highCapacityPeers.size(); } } - public int countWellIntegratedPeers() { synchronized (_reorganizeLock) { return _wellIntegratedPeers.size(); } } - public int countNotFailingPeers() { synchronized (_reorganizeLock) { return _notFailingPeers.size(); } } - public int countFailingPeers() { synchronized (_reorganizeLock) { return _failingPeers.size(); } } + private int count(Map m) { + getReadLock(); + try { + return m.size(); + } finally { releaseReadLock(); } + } + + public int countFastPeers() { return count(_fastPeers); } + public int countHighCapacityPeers() { return count(_highCapacityPeers); } + public int countWellIntegratedPeers() { return count(_wellIntegratedPeers); } + public int countNotFailingPeers() { return count(_notFailingPeers); } + public int countFailingPeers() { return count(_failingPeers); } public int countActivePeers() { - synchronized (_reorganizeLock) { - int activePeers = 0; - - long hideBefore = _context.clock().now() - 6*60*60*1000; - + int activePeers = 0; + long hideBefore = _context.clock().now() - 6*60*60*1000; + + getReadLock(); + try { for (Iterator iter = _failingPeers.values().iterator(); iter.hasNext(); ) { PeerProfile profile = (PeerProfile)iter.next(); if (profile.getLastSendSuccessful() >= hideBefore) @@ -174,15 +209,21 @@ public class ProfileOrganizer { else if (profile.getLastHeardFrom() >= hideBefore) activePeers++; } - - return activePeers; - } + } finally { releaseReadLock(); } + return activePeers; } - public boolean isFast(Hash peer) { synchronized (_reorganizeLock) { return _fastPeers.containsKey(peer); } } - public boolean isHighCapacity(Hash peer) { synchronized (_reorganizeLock) { return _highCapacityPeers.containsKey(peer); } } - public boolean isWellIntegrated(Hash peer) { synchronized (_reorganizeLock) { return _wellIntegratedPeers.containsKey(peer); } } - public boolean isFailing(Hash peer) { synchronized (_reorganizeLock) { return _failingPeers.containsKey(peer); } } + private boolean isX(Map m, Hash peer) { + getReadLock(); + try { + return m.containsKey(peer); + } finally { releaseReadLock(); } + } + + public boolean isFast(Hash peer) { return isX(_fastPeers, peer); } + public boolean isHighCapacity(Hash peer) { return isX(_highCapacityPeers, peer); } + public boolean isWellIntegrated(Hash peer) { return isX(_wellIntegratedPeers, peer); } + public boolean isFailing(Hash peer) { return isX(_failingPeers, peer); } /** * if a peer sends us more than 5 replies in a searchReply that we cannot @@ -236,9 +277,10 @@ public class ProfileOrganizer { selectFastPeers(howMany, exclude, matches, 0); } public void selectFastPeers(int howMany, Set exclude, Set matches, int mask) { - synchronized (_reorganizeLock) { + getReadLock(); + try { locked_selectPeers(_fastPeers, howMany, exclude, matches, mask); - } + } finally { releaseReadLock(); } if (matches.size() < howMany) { if (_log.shouldLog(Log.INFO)) _log.info("selectFastPeers("+howMany+"), not enough fast (" + matches.size() + ") going on to highCap"); @@ -258,7 +300,8 @@ public class ProfileOrganizer { selectHighCapacityPeers(howMany, exclude, matches, 0); } public void selectHighCapacityPeers(int howMany, Set exclude, Set matches, int mask) { - synchronized (_reorganizeLock) { + getReadLock(); + try { // we only use selectHighCapacityPeers when we are selecting for PURPOSE_TEST // or we are falling back due to _fastPeers being too small, so we can always // exclude the fast peers @@ -269,7 +312,7 @@ public class ProfileOrganizer { exclude.addAll(_fastPeers.keySet()); */ locked_selectPeers(_highCapacityPeers, howMany, exclude, matches, mask); - } + } finally { releaseReadLock(); } if (matches.size() < howMany) { if (_log.shouldLog(Log.INFO)) _log.info("selectHighCap("+howMany+"), not enough fast (" + matches.size() + ") going on to notFailing"); @@ -288,9 +331,10 @@ public class ProfileOrganizer { selectWellIntegratedPeers(howMany, exclude, matches, 0); } public void selectWellIntegratedPeers(int howMany, Set exclude, Set matches, int mask) { - synchronized (_reorganizeLock) { + getReadLock(); + try { locked_selectPeers(_wellIntegratedPeers, howMany, exclude, matches, mask); - } + } finally { releaseReadLock(); } if (matches.size() < howMany) { if (_log.shouldLog(Log.INFO)) _log.info("selectWellIntegrated("+howMany+"), not enough integrated (" + matches.size() + ") going on to notFailing"); @@ -375,7 +419,8 @@ public class ProfileOrganizer { int needed = howMany - orig; int start = 0; List selected = new ArrayList(needed); - synchronized (_reorganizeLock) { + getReadLock(); + try { // we randomize the whole list when rebuilding it, but randomizing // the entire list on each peer selection is a bit crazy start = _context.random().nextInt(_notFailingPeersList.size()); @@ -397,7 +442,7 @@ public class ProfileOrganizer { _log.debug("Not selectable: " + cur.toBase64()); } } - } + } finally { releaseReadLock(); } if (_log.shouldLog(Log.INFO)) _log.info("Selecting all not failing (strict? " + onlyNotFailing + " start=" + start + ") found " + selected.size() + " new peers: " + selected + " all=" + _notFailingPeersList.size() + " strict=" + _strictCapacityOrder.size()); @@ -418,25 +463,27 @@ public class ProfileOrganizer { * */ public void selectFailingPeers(int howMany, Set exclude, Set matches) { - synchronized (_reorganizeLock) { + getReadLock(); + try { locked_selectPeers(_failingPeers, howMany, exclude, matches); - } - return; - } - - /** + } finally { releaseReadLock(); } + return; + } + + /** * Get the peers the transport layer thinks are unreachable, and * add in the peers with the SSU peer testing bug, * and peers requiring introducers. - * - */ + * + */ public List selectPeersLocallyUnreachable() { List n; int count; - synchronized (_reorganizeLock) { + getReadLock(); + try { count = _notFailingPeers.size(); n = new ArrayList(_notFailingPeers.keySet()); - } + } finally { releaseReadLock(); } List l = new ArrayList(count / 4); for (Iterator iter = n.iterator(); iter.hasNext(); ) { Hash peer = (Hash)iter.next(); @@ -483,7 +530,8 @@ public class ProfileOrganizer { * */ public List selectPeersRecentlyRejecting() { - synchronized (_reorganizeLock) { + getReadLock(); + try { long cutoff = _context.clock().now() - (20*1000); int count = _notFailingPeers.size(); List l = new ArrayList(count / 128); @@ -493,7 +541,7 @@ public class ProfileOrganizer { l.add(prof.getPeer()); } return l; - } + } finally { releaseReadLock(); } } /** @@ -501,14 +549,15 @@ public class ProfileOrganizer { * */ public Set selectAllPeers() { - synchronized (_reorganizeLock) { + getReadLock(); + try { Set allPeers = new HashSet(_failingPeers.size() + _notFailingPeers.size() + _highCapacityPeers.size() + _fastPeers.size()); allPeers.addAll(_failingPeers.keySet()); allPeers.addAll(_notFailingPeers.keySet()); allPeers.addAll(_highCapacityPeers.keySet()); allPeers.addAll(_fastPeers.keySet()); return allPeers; - } + } finally { releaseReadLock(); } } /** @@ -532,8 +581,10 @@ public class ProfileOrganizer { expireOlderThan = _context.clock().now() - 6*60*60*1000; } + if (!getWriteLock()) + return; long start = System.currentTimeMillis(); - synchronized (_reorganizeLock) { + try { Set allPeers = _strictCapacityOrder; //new HashSet(_failingPeers.size() + _notFailingPeers.size() + _highCapacityPeers.size() + _fastPeers.size()); //allPeers.addAll(_failingPeers.values()); //allPeers.addAll(_notFailingPeers.values()); @@ -557,35 +608,37 @@ public class ProfileOrganizer { } sortTime = System.currentTimeMillis() - sortStart; _strictCapacityOrder = reordered; - + long thresholdStart = System.currentTimeMillis(); locked_calculateThresholds(allPeers); thresholdTime = System.currentTimeMillis()-thresholdStart; - + _failingPeers.clear(); _fastPeers.clear(); _highCapacityPeers.clear(); _notFailingPeers.clear(); _notFailingPeersList.clear(); _wellIntegratedPeers.clear(); - + long placeStart = System.currentTimeMillis(); - + for (Iterator iter = allPeers.iterator(); iter.hasNext(); ) { PeerProfile profile = (PeerProfile)iter.next(); locked_placeProfile(profile); } - + locked_unfailAsNecessary(); locked_promoteFastAsNecessary(); Collections.shuffle(_notFailingPeersList, _context.random()); - + placeTime = System.currentTimeMillis()-placeStart; + } finally { releaseWriteLock(); } - if (_log.shouldLog(Log.INFO)) - _log.info("Profiles reorganized. averages: [integration: " + _thresholdIntegrationValue - + ", capacity: " + _thresholdCapacityValue + ", speed: " + _thresholdSpeedValue + "]"); + + if (_log.shouldLog(Log.INFO)) + _log.info("Profiles reorganized. averages: [integration: " + _thresholdIntegrationValue + + ", capacity: " + _thresholdCapacityValue + ", speed: " + _thresholdSpeedValue + "]"); /***** if (_log.shouldLog(Log.DEBUG)) { StringBuffer buf = new StringBuffer(512); @@ -597,7 +650,6 @@ public class ProfileOrganizer { _log.debug("fast: " + _fastPeers.values()); } *****/ - } long total = System.currentTimeMillis()-start; _context.statManager().addRateData("peer.profileSortTime", sortTime, profileCount); @@ -899,11 +951,12 @@ public class ProfileOrganizer { all.removeAll(matches); all.remove(_us); Collections.shuffle(all, _random); + Set IPSet = new HashSet(8); for (int i = 0; (matches.size() < howMany) && (i < all.size()); i++) { Hash peer = (Hash)all.get(i); boolean ok = isSelectable(peer); if (ok) { - ok = mask <= 0 || notRestricted(peer, matches, mask); + ok = mask <= 0 || notRestricted(peer, IPSet, mask); if ((!ok) && _log.shouldLog(Log.WARN)) _log.warn("IP restriction prevents " + peer + " from joining " + matches); } @@ -917,77 +970,67 @@ public class ProfileOrganizer { /** * Does the peer's IP address NOT match the IP address of any peer already in the set, * on any transport, within a given mask? - * mask is 1-4 (number of bytes to match) or 0 to disable - * Perhaps rewrite this to just make a set of all the IP addresses rather than loop. + * @param mask is 1-4 (number of bytes to match) + * @param IPMatches all IPs so far, modified by this routine */ - private boolean notRestricted(Hash peer, Set matches, int mask) { - if (mask <= 0) return true; - if (matches.size() <= 0) return true; - RouterInfo pinfo = _context.netDb().lookupRouterInfoLocally(peer); - if (pinfo == null) return false; - Set paddr = pinfo.getAddresses(); - if (paddr == null || paddr.size() == 0) + private boolean notRestricted(Hash peer, Set IPSet, int mask) { + Set peerIPs = maskedIPSet(peer, mask); + if (containsAny(IPSet, peerIPs)) return false; - List pladdr = new ArrayList(paddr); - List lmatches = new ArrayList(matches); - // for each match - for (int i = 0; i < matches.size(); i++) { - RouterInfo minfo = _context.netDb().lookupRouterInfoLocally((Hash) lmatches.get(i)); - if (minfo == null) continue; - Set maddr = minfo.getAddresses(); - if (maddr == null || maddr.size() == 0) + IPSet.addAll(peerIPs); + return true; + } + + /** + * The Set of IPs for this peer, with a given mask. + * Includes the comm system's record of the IP, and all netDb addresses. + * + * @return an opaque set of masked IPs for this peer + */ + private Set maskedIPSet(Hash peer, int mask) { + Set rv = new HashSet(2); + byte[] commIP = _context.commSystem().getIP(peer); + if (commIP != null) + rv.add(maskedIP(commIP, mask)); + RouterInfo pinfo = _context.netDb().lookupRouterInfoLocally(peer); + if (pinfo == null) + return rv; + Set<RouterAddress> paddr = pinfo.getAddresses(); + if (paddr == null) + return rv; + for (RouterAddress pa : paddr) { + Properties pprops = pa.getOptions(); + if (pprops == null) continue; + String phost = pprops.getProperty("host"); + if (phost == null) continue; + InetAddress pi; + try { + pi = InetAddress.getByName(phost); + } catch (UnknownHostException uhe) { continue; - List mladdr = new ArrayList(maddr); - String oldphost = null; - // for each peer address - for (int j = 0; j < paddr.size(); j++) { - RouterAddress pa = (RouterAddress) pladdr.get(j); - if (pa == null) continue; - Properties pprops = pa.getOptions(); - if (pprops == null) continue; - String phost = pprops.getProperty("host"); - if (phost == null) continue; - if (oldphost != null && oldphost.equals(phost)) continue; - oldphost = phost; - InetAddress pi; - try { - pi = InetAddress.getByName(phost); - } catch (UnknownHostException uhe) { - continue; - } - if (pi == null) continue; - byte[] pib = pi.getAddress(); - String oldmhost = null; - // for each match address - for (int k = 0; k < maddr.size(); k++) { - RouterAddress ma = (RouterAddress) mladdr.get(k); - if (ma == null) continue; - Properties mprops = ma.getOptions(); - if (mprops == null) continue; - String mhost = mprops.getProperty("host"); - if (mhost == null) continue; - if (oldmhost != null && oldmhost.equals(mhost)) continue; - oldmhost = mhost; - InetAddress mi; - try { - mi = InetAddress.getByName(mhost); - } catch (UnknownHostException uhe) { - continue; - } - if (mi == null) continue; - byte[] mib = mi.getAddress(); - // assume ipv4, compare 1 to 4 bytes - // log.info("Comparing " + pi + " with " + mi); - for (int m = 0; m < mask; m++) { - if (pib[m] != mib[m]) - break; - if (m == mask-1) - return false; // IP match - } - } } + if (pi == null) continue; + byte[] pib = pi.getAddress(); + rv.add(maskedIP(pib, mask)); } - return true; + return rv; + } + + /** generate an arbitrary unique value for this ip/mask (mask = 1-4) */ + private Integer maskedIP(byte[] ip, int mask) { + int rv = 0; + for (int i = 0; i < mask; i++) + rv = (rv << 8) | (ip[i] & 0xff); + return Integer.valueOf(rv); + } + + /** does a contain any of the elements in b? */ + private boolean containsAny(Set a, Set b) { + for (Object o : b) { + if (a.contains(o)) + return true; + } + return false; } public boolean isSelectable(Hash peer) { diff --git a/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java b/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java index 2671c8be05ad8e72927bc983d97d7feaba383c49..b665f495c156d4e0c18378ff515dbf0eeff0e225 100644 --- a/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java +++ b/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java @@ -3,10 +3,8 @@ package net.i2p.router.peermanager; import java.io.IOException; import java.io.Writer; import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; import java.util.Comparator; import java.util.Iterator; -import java.util.Locale; import java.util.Set; import java.util.TreeSet; diff --git a/router/java/src/net/i2p/router/peermanager/SpeedCalculator.java b/router/java/src/net/i2p/router/peermanager/SpeedCalculator.java index a7fc9334778883cfadcbff336fc59137b9c970ca..c5ac1c3c56d26871dc33beec002063983fd5c70b 100644 --- a/router/java/src/net/i2p/router/peermanager/SpeedCalculator.java +++ b/router/java/src/net/i2p/router/peermanager/SpeedCalculator.java @@ -18,6 +18,7 @@ public class SpeedCalculator extends Calculator { public SpeedCalculator(RouterContext context) { } + @Override public double calc(PeerProfile profile) { // measures 1 minute throughput of individual tunnels double d = (profile.getPeakTunnel1mThroughputKBps()*1024d) + profile.getSpeedBonus(); diff --git a/router/java/src/net/i2p/router/transport/BandwidthLimitedInputStream.java b/router/java/src/net/i2p/router/transport/BandwidthLimitedInputStream.java index ffd041019108e6ce92b4bd7ce942e56543fdd547..f47394eff1e764932c59a137ae760ade310e72f4 100644 --- a/router/java/src/net/i2p/router/transport/BandwidthLimitedInputStream.java +++ b/router/java/src/net/i2p/router/transport/BandwidthLimitedInputStream.java @@ -41,6 +41,7 @@ public class BandwidthLimitedInputStream extends FilterInputStream { _log = context.logManager().getLog(BandwidthLimitedInputStream.class); } + @Override public int read() throws IOException { if (_pullFromOutbound) _currentRequest = _context.bandwidthLimiter().requestOutbound(1, _peerSource); @@ -56,10 +57,12 @@ public class BandwidthLimitedInputStream extends FilterInputStream { return in.read(); } + @Override public int read(byte dest[]) throws IOException { return read(dest, 0, dest.length); } + @Override public int read(byte dest[], int off, int len) throws IOException { int read = in.read(dest, off, len); if (read == -1) return -1; @@ -84,6 +87,7 @@ public class BandwidthLimitedInputStream extends FilterInputStream { } return read; } + @Override public long skip(long numBytes) throws IOException { long skip = in.skip(numBytes); @@ -105,6 +109,7 @@ public class BandwidthLimitedInputStream extends FilterInputStream { return skip; } + @Override public void close() throws IOException { synchronized (this) { if (_currentRequest != null) diff --git a/router/java/src/net/i2p/router/transport/BandwidthLimitedOutputStream.java b/router/java/src/net/i2p/router/transport/BandwidthLimitedOutputStream.java index df37d951416303c7c57d0cfc4c434d0ab19b3831..0327fd25ed3cdd9346816304c68bb5530f778da8 100644 --- a/router/java/src/net/i2p/router/transport/BandwidthLimitedOutputStream.java +++ b/router/java/src/net/i2p/router/transport/BandwidthLimitedOutputStream.java @@ -37,6 +37,7 @@ public class BandwidthLimitedOutputStream extends FilterOutputStream { public FIFOBandwidthLimiter.Request getCurrentRequest() { return _currentRequest; } + @Override public void write(int val) throws IOException { if (_log.shouldLog(Log.DEBUG)) _log.debug("Writing a single byte!", new Exception("Single byte from...")); @@ -49,9 +50,11 @@ public class BandwidthLimitedOutputStream extends FilterOutputStream { _log.warn("Waiting to write a byte took too long [" + waited + "ms"); out.write(val); } + @Override public void write(byte src[]) throws IOException { write(src, 0, src.length); } + @Override public void write(byte src[], int off, int len) throws IOException { if (_log.shouldLog(Log.DEBUG)) _log.debug("Writing " + len + " bytes"); @@ -83,6 +86,7 @@ public class BandwidthLimitedOutputStream extends FilterOutputStream { } } + @Override public void close() throws IOException { synchronized (this) { if (_currentRequest != null) diff --git a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java index 0eafb8fa9755da49cfbad97329af462a56d0011b..217054d4054f7682a9be005a9e4070464588cd0a 100644 --- a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java +++ b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java @@ -58,14 +58,18 @@ public class CommSystemFacadeImpl extends CommSystemFacade { _manager.restart(); } + @Override public int countActivePeers() { return (_manager == null ? 0 : _manager.countActivePeers()); } + @Override public int countActiveSendPeers() { return (_manager == null ? 0 : _manager.countActiveSendPeers()); } + @Override public boolean haveCapacity() { return (_manager == null ? false : _manager.haveCapacity()); } /** * Framed average clock skew of connected peers in seconds, or null if we cannot answer. * Average is calculated over the middle "percentToInclude" peers. */ + @Override public Long getFramedAveragePeerClockSkew(int percentToInclude) { if (_manager == null) { if (_log.shouldLog(Log.INFO)) @@ -121,14 +125,17 @@ public class CommSystemFacadeImpl extends CommSystemFacade { GetBidsJob.getBids(_context, this, msg); } + @Override public boolean isBacklogged(Hash dest) { return _manager.isBacklogged(dest); } + @Override public boolean isEstablished(Hash dest) { return _manager.isEstablished(dest); } + @Override public boolean wasUnreachable(Hash dest) { return _manager.wasUnreachable(dest); } @@ -137,21 +144,26 @@ public class CommSystemFacadeImpl extends CommSystemFacade { return _manager.getIP(dest); } + @Override public List getMostRecentErrorMessages() { return _manager.getMostRecentErrorMessages(); } + @Override public short getReachabilityStatus() { if (_manager == null) return CommSystemFacade.STATUS_UNKNOWN; if (_context.router().isHidden()) return CommSystemFacade.STATUS_OK; return _manager.getReachabilityStatus(); } + @Override public void recheckReachability() { _manager.recheckReachability(); } + @Override public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException { _manager.renderStatusHTML(out, urlBase, sortFlags); } + @Override public Set createAddresses() { Map addresses = null; boolean newCreated = false; @@ -178,8 +190,8 @@ public class CommSystemFacadeImpl extends CommSystemFacade { public final static String PROP_I2NP_NTCP_HOSTNAME = "i2np.ntcp.hostname"; public final static String PROP_I2NP_NTCP_PORT = "i2np.ntcp.port"; - public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoip"; - public final static String PROP_I2NP_NTCP_AUTO_IP = "i2np.ntcp.autoport"; + public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoport"; + public final static String PROP_I2NP_NTCP_AUTO_IP = "i2np.ntcp.autoip"; public static RouterAddress createNTCPAddress(RouterContext ctx) { if (!TransportManager.enableNTCP(ctx)) return null; @@ -225,6 +237,7 @@ public class CommSystemFacadeImpl extends CommSystemFacade { /** * UDP changed addresses, tell NTCP and restart */ + @Override public void notifyReplaceAddress(RouterAddress UDPAddr) { if (UDPAddr == null) return; diff --git a/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java b/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java index 63bf736536e7d8d6f54d7ff1c409ec3847d3f91a..1f643b48df7fb23ce21226f8b6dbe15514383852 100644 --- a/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java +++ b/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java @@ -12,8 +12,8 @@ import net.i2p.util.Log; public class FIFOBandwidthLimiter { private Log _log; private I2PAppContext _context; - private List _pendingInboundRequests; - private List _pendingOutboundRequests; + private final List _pendingInboundRequests; + private final List _pendingOutboundRequests; /** how many bytes we can consume for inbound transmission immediately */ private volatile int _availableInbound; /** how many bytes we can consume for outbound transmission immediately */ @@ -54,7 +54,7 @@ public class FIFOBandwidthLimiter { private static int __id = 0; - static long now() { + public /* static */ long now() { // dont use the clock().now(), since that may jump return System.currentTimeMillis(); } @@ -769,6 +769,7 @@ public class FIFOBandwidthLimiter { } public void attach(Object obj) { _attachment = obj; } public Object attachment() { return _attachment; } + @Override public String toString() { return getRequestName(); } } diff --git a/router/java/src/net/i2p/router/transport/OutboundMessageRegistry.java b/router/java/src/net/i2p/router/transport/OutboundMessageRegistry.java index c5ca48f57acf64b5e5f7fe462e49be2177bbb583..17108a8e87c2cf67dd28d8f6c4f10af24dafad0a 100644 --- a/router/java/src/net/i2p/router/transport/OutboundMessageRegistry.java +++ b/router/java/src/net/i2p/router/transport/OutboundMessageRegistry.java @@ -30,11 +30,11 @@ import net.i2p.util.SimpleTimer; public class OutboundMessageRegistry { private Log _log; /** list of currently active MessageSelector instances */ - private List _selectors; + private final List _selectors; /** map of active MessageSelector to either an OutNetMessage or a List of OutNetMessages causing it (for quick removal) */ - private Map _selectorToMessage; + private final Map _selectorToMessage; /** set of active OutNetMessage (for quick removal and selector fetching) */ - private Set _activeMessages; + private final Set _activeMessages; private CleanupTask _cleanupTask; private RouterContext _context; diff --git a/router/java/src/net/i2p/router/transport/TransportImpl.java b/router/java/src/net/i2p/router/transport/TransportImpl.java index 930734d43ccde0facf795dda0e51d5987e58d554..cff0d9a468275676760f261793095e07803c452e 100644 --- a/router/java/src/net/i2p/router/transport/TransportImpl.java +++ b/router/java/src/net/i2p/router/transport/TransportImpl.java @@ -36,6 +36,8 @@ import net.i2p.router.RouterContext; import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade; import net.i2p.util.ConcurrentHashSet; import net.i2p.util.Log; +import net.i2p.util.SimpleScheduler; +import net.i2p.util.SimpleTimer; /** * Defines a way to send a message to another peer and start listening for messages @@ -72,6 +74,7 @@ public abstract class TransportImpl implements Transport { _unreachableEntries = new HashMap(16); _wasUnreachableEntries = new ConcurrentHashSet(16); _currentAddress = null; + SimpleScheduler.getInstance().addPeriodicEvent(new CleanupUnreachable(), 2 * UNREACHABLE_PERIOD, UNREACHABLE_PERIOD / 2); } /** @@ -464,13 +467,10 @@ public abstract class TransportImpl implements Transport { if (!isInbound) markWasUnreachable(peer, false); } - private class CleanupUnreachable extends JobImpl { - public CleanupUnreachable(RouterContext ctx) { - super(ctx); - } - public String getName() { return "Cleanup " + getStyle() + " unreachable list"; } - public void runJob() { - long now = getContext().clock().now(); + + private class CleanupUnreachable implements SimpleTimer.TimedEvent { + public void timeReached() { + long now = _context.clock().now(); synchronized (_unreachableEntries) { for (Iterator iter = _unreachableEntries.keySet().iterator(); iter.hasNext(); ) { Hash peer = (Hash)iter.next(); @@ -479,7 +479,6 @@ public abstract class TransportImpl implements Transport { iter.remove(); } } - requeue(60*1000); } } diff --git a/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java b/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java index 0c062fa6cf2330a47f11dcd091a0638f51e8b936..24ac63c6b28bfde33a0b98eb85306bbf9c9ea5a1 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java +++ b/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java @@ -33,11 +33,11 @@ public class EventPumper implements Runnable { private Log _log; private boolean _alive; private Selector _selector; - private List _bufCache; - private List _wantsRead; - private List _wantsWrite; - private List _wantsRegister; - private List _wantsConRegister; + private final List _bufCache; + private final List _wantsRead = new ArrayList(16); + private final List _wantsWrite = new ArrayList(4); + private final List _wantsRegister = new ArrayList(1); + private final List _wantsConRegister = new ArrayList(4); private NTCPTransport _transport; private long _expireIdleWriteTime; @@ -66,10 +66,10 @@ public class EventPumper implements Runnable { public void startPumping() { if (_log.shouldLog(Log.INFO)) _log.info("Starting pumper"); - _wantsRead = new ArrayList(16); - _wantsWrite = new ArrayList(4); - _wantsRegister = new ArrayList(1); - _wantsConRegister = new ArrayList(4); +// _wantsRead = new ArrayList(16); +// _wantsWrite = new ArrayList(4); +// _wantsRegister = new ArrayList(1); +// _wantsConRegister = new ArrayList(4); try { _selector = Selector.open(); _alive = true; diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPAddress.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPAddress.java index 71d395e5f0b9b0b94622c4c5ad2c91419fcae415..860634d8f5620d47b9809b27afd40ea66c36f870 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/NTCPAddress.java +++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPAddress.java @@ -124,8 +124,10 @@ public class NTCPAddress { } } + @Override public String toString() { return _host + ":" + _port; } + @Override public int hashCode() { int rv = 0; rv += _port; @@ -136,6 +138,7 @@ public class NTCPAddress { return rv; } + @Override public boolean equals(Object val) { if ( (val != null) && (val instanceof NTCPAddress) ) { NTCPAddress addr = (NTCPAddress)val; diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPConnection.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPConnection.java index 070caae84c9cda31c058b3f9c85ed53674c34c3d..3acabafdc48a809aa199d060c90230684eda25d0 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/NTCPConnection.java +++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPConnection.java @@ -56,13 +56,13 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener { private SocketChannel _chan; private SelectionKey _conKey; /** list of ByteBuffer containing data we have read and are ready to process, oldest first */ - private List _readBufs; + private final List _readBufs; /** * list of ByteBuffers containing fully populated and encrypted data, ready to write, * and already cleared through the bandwidth limiter. */ - private List _writeBufs; - private List _bwRequests; + private final List _writeBufs; + private final List _bwRequests; private boolean _established; private long _establishedOn; private EstablishState _establishState; @@ -75,7 +75,7 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener { /** * pending unprepared OutNetMessage instances */ - private List _outbound; + private final List _outbound; /** current prepared OutNetMessage, or null */ private OutNetMessage _currentOutbound; private SessionKey _sessionKey; @@ -96,7 +96,7 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener { private long _created; private long _nextMetaTime; /** unencrypted outbound metadata buffer */ - private byte _meta[] = new byte[16]; + private final byte _meta[] = new byte[16]; private boolean _sendingMeta; /** how many consecutive sends were failed due to (estimated) send queue time */ private int _consecutiveBacklog; @@ -398,6 +398,8 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener { continue; RouterInfo info = fac.lookupRouterInfoLocally(peer); + if (info == null) + continue; OutNetMessage infoMsg = new OutNetMessage(_context); infoMsg.setExpiration(_context.clock().now()+10*1000); @@ -704,7 +706,7 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener { private static int NUM_PREP_BUFS = 5; private static int __liveBufs = 0; private static int __consecutiveExtra; - private static List _bufs = new ArrayList(NUM_PREP_BUFS); + private final static List _bufs = new ArrayList(NUM_PREP_BUFS); private PrepBuffer acquireBuf() { synchronized (_bufs) { if (_bufs.size() > 0) { @@ -1093,11 +1095,17 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener { // enqueueInfoMessage(); // this often? } + @Override public int hashCode() { return System.identityHashCode(this); } - public boolean equals(Object obj) { return obj == this; } + @Override + public boolean equals(Object obj) { + if(obj == null) return false; + if(obj.getClass() != NTCPConnection.class) return false; + return obj == this; + } - private static List _i2npHandlers = new ArrayList(4); - private static I2NPMessageHandler acquireHandler(RouterContext ctx) { + private final static List _i2npHandlers = new ArrayList(4); + private final static I2NPMessageHandler acquireHandler(RouterContext ctx) { I2NPMessageHandler rv = null; synchronized (_i2npHandlers) { if (_i2npHandlers.size() > 0) @@ -1127,7 +1135,7 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener { } private static int MAX_DATA_READ_BUFS = 16; - private static List _dataReadBufs = new ArrayList(16); + private final static List _dataReadBufs = new ArrayList(16); private static DataBuf acquireReadBuf() { synchronized (_dataReadBufs) { if (_dataReadBufs.size() > 0) @@ -1289,6 +1297,7 @@ public class NTCPConnection implements FIFOBandwidthLimiter.CompleteListener { } } + @Override public String toString() { return "NTCP Connection to " + (_remotePeer == null ? "unknown " : _remotePeer.calculateHash().toBase64().substring(0,6)) + diff --git a/router/java/src/net/i2p/router/transport/ntcp/Reader.java b/router/java/src/net/i2p/router/transport/ntcp/Reader.java index 4b4dc3db1224551d3c1e06815ae07493eec917cb..2c017b5b6df696238ed16734d08ff375bbd593d7 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/Reader.java +++ b/router/java/src/net/i2p/router/transport/ntcp/Reader.java @@ -17,7 +17,7 @@ import net.i2p.util.Log; class Reader { private RouterContext _context; private Log _log; - private List _pendingConnections; + private final List _pendingConnections; private List _liveReads; private List _readAfterLive; private List _runners; diff --git a/router/java/src/net/i2p/router/transport/ntcp/Writer.java b/router/java/src/net/i2p/router/transport/ntcp/Writer.java index 29b7258167a046cef4baaeeedfaeb0942be23497..97823313bc281ac21da7fa74c3811c66a0358201 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/Writer.java +++ b/router/java/src/net/i2p/router/transport/ntcp/Writer.java @@ -16,7 +16,7 @@ import net.i2p.util.Log; class Writer { private RouterContext _context; private Log _log; - private List _pendingConnections; + private final List _pendingConnections; private List _liveWrites; private List _writeAfterLive; private List _runners; diff --git a/router/java/src/net/i2p/router/transport/udp/ACKSender.java b/router/java/src/net/i2p/router/transport/udp/ACKSender.java index 66aad6f4d092e211af2c99b627ec708057fc9ab7..e2a21ca4a981dcbde735e92806edb6fbbdaf0456 100644 --- a/router/java/src/net/i2p/router/transport/udp/ACKSender.java +++ b/router/java/src/net/i2p/router/transport/udp/ACKSender.java @@ -18,7 +18,7 @@ public class ACKSender implements Runnable { private UDPTransport _transport; private PacketBuilder _builder; /** list of peers (PeerState) who we have received data from but not yet ACKed to */ - private List _peersToACK; + private final List _peersToACK; private boolean _alive; /** how frequently do we want to send ACKs to a peer? */ diff --git a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java index e8731da05f0dcdfd981f5a1f8403261173e49f92..d36a3053d25e879da61e64ac6e8597fd4baa4a6a 100644 --- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java +++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java @@ -670,7 +670,7 @@ public class EstablishmentManager { } } - public void receiveRelayResponse(RemoteHostId bob, UDPPacketReader reader) { + public void receiveRelayResponse(RemoteHostId bob, UDPPacketReader reader) {// LINT -- Exporting non-public type through public API long nonce = reader.getRelayResponseReader().readNonce(); OutboundEstablishState state = null; synchronized (_liveIntroductions) { diff --git a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java index ababfa7c4cc4e33ecd9765d84afc13283b75acb3..290a5139b060c81018be0cc21b735b26e4bae32a 100644 --- a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java @@ -210,7 +210,7 @@ public class InboundEstablishState { public synchronized void setNextSendTime(long when) { _nextSend = when; } /** RemoteHostId, uniquely identifies an attempt */ - public RemoteHostId getRemoteHostId() { return _remoteHostId; } + public RemoteHostId getRemoteHostId() { return _remoteHostId; }// LINT -- Exporting non-public type through public API public synchronized void receiveSessionConfirmed(UDPPacketReader.SessionConfirmedReader conf) { if (_receivedIdentity == null) @@ -331,6 +331,7 @@ public class InboundEstablishState { _nextSend = _lastReceive; } + @Override public String toString() { StringBuffer buf = new StringBuffer(128); buf.append(super.toString()); diff --git a/router/java/src/net/i2p/router/transport/udp/InboundMessageState.java b/router/java/src/net/i2p/router/transport/udp/InboundMessageState.java index a99929f40f6437ed201310c7e67fc79b8caf7823..6c85b9fb72960a1cb394cd1cc8c279dde43eb517 100644 --- a/router/java/src/net/i2p/router/transport/udp/InboundMessageState.java +++ b/router/java/src/net/i2p/router/transport/udp/InboundMessageState.java @@ -138,6 +138,7 @@ public class InboundMessageState { } public boolean receivedComplete() { return false; } + @Override public String toString() { StringBuffer buf = new StringBuffer(64); buf.append("Partial ACK of "); @@ -162,6 +163,7 @@ public class InboundMessageState { } public int getFragmentCount() { return _lastFragment+1; } + @Override public String toString() { StringBuffer buf = new StringBuffer(32); buf.append("Message: ").append(_messageId); diff --git a/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java b/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java index bbbc35caba65b430c75a4b5687078f3f53662f34..25ab9ab6a1a01b033cece91c3a2deca9a7021410 100644 --- a/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java +++ b/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java @@ -25,7 +25,7 @@ public class IntroductionManager { /** map of relay tag to PeerState that should receive the introduction */ private Map _outbound; /** list of peers (PeerState) who have given us introduction tags */ - private List _inbound; + private final List _inbound; public IntroductionManager(RouterContext ctx, UDPTransport transport) { _context = ctx; @@ -157,7 +157,7 @@ public class IntroductionManager { return found; } - public void receiveRelayIntro(RemoteHostId bob, UDPPacketReader reader) { + public void receiveRelayIntro(RemoteHostId bob, UDPPacketReader reader) {// LINT -- Exporting non-public type through public API if (_context.router().isHidden()) return; if (_log.shouldLog(Log.INFO)) @@ -166,7 +166,7 @@ public class IntroductionManager { _transport.send(_builder.buildHolePunch(reader)); } - public void receiveRelayRequest(RemoteHostId alice, UDPPacketReader reader) { + public void receiveRelayRequest(RemoteHostId alice, UDPPacketReader reader) {// LINT -- Exporting non-public type through public API if (_context.router().isHidden()) return; long tag = reader.getRelayRequestReader().readTag(); diff --git a/router/java/src/net/i2p/router/transport/udp/MessageReceiver.java b/router/java/src/net/i2p/router/transport/udp/MessageReceiver.java index a6a75459efcf9786b641a24bd5604db64f3b1579..61c75c99e83d4a46e198f98a7a0b717e9457fce0 100644 --- a/router/java/src/net/i2p/router/transport/udp/MessageReceiver.java +++ b/router/java/src/net/i2p/router/transport/udp/MessageReceiver.java @@ -24,7 +24,7 @@ public class MessageReceiver { private Log _log; private UDPTransport _transport; /** list of messages (InboundMessageState) fully received but not interpreted yet */ - private List _completeMessages; + private final List _completeMessages; private boolean _alive; private ByteCache _cache; diff --git a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java index fc424de5bf58d40200aa27201135dc34ed369033..47a54ce116a6d23f44fc357975a6351b8127dabb 100644 --- a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java @@ -51,7 +51,7 @@ public class OutboundEstablishState { private RemoteHostId _remoteHostId; private RouterIdentity _remotePeer; private SessionKey _introKey; - private List _queuedMessages; + private final List _queuedMessages; private int _currentState; private long _introductionNonce; // intro @@ -413,7 +413,7 @@ public class OutboundEstablishState { } /** uniquely identifies an attempt */ - public RemoteHostId getRemoteHostId() { return _remoteHostId; } + public RemoteHostId getRemoteHostId() { return _remoteHostId; }// LINT -- Exporting non-public type through public API /** we have received a real data packet, so we're done establishing */ public synchronized void dataReceived() { diff --git a/router/java/src/net/i2p/router/transport/udp/OutboundMessageState.java b/router/java/src/net/i2p/router/transport/udp/OutboundMessageState.java index fc6896627ed6b3be91148c232418f794ef36bb85..c9e7db02c5bf48eb08eba8af78b11f719afd738e 100644 --- a/router/java/src/net/i2p/router/transport/udp/OutboundMessageState.java +++ b/router/java/src/net/i2p/router/transport/udp/OutboundMessageState.java @@ -286,6 +286,7 @@ public class OutboundMessageState { } } + @Override public String toString() { short sends[] = _fragmentSends; ByteArray messageBuf = _messageBuf; diff --git a/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java b/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java index f00587bcd1b564142e0968d9c63ef850f2ad2203..dcdf5fb6d95f95ca7ed7fd830415f85b408b8559 100644 --- a/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java +++ b/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java @@ -786,6 +786,7 @@ public class PacketBuilder { private int getOurExplicitPort() { return 0; } /** build intro packets for each of the published introducers */ + @SuppressWarnings("static-access") public UDPPacket[] buildRelayRequest(UDPTransport transport, OutboundEstablishState state, SessionKey ourIntroKey) { UDPAddress addr = state.getRemoteAddress(); int count = addr.getIntroducerCount(); @@ -878,7 +879,7 @@ public class PacketBuilder { */ private static final byte PEER_RELAY_INTRO_FLAG_BYTE = (UDPPacket.PAYLOAD_TYPE_RELAY_INTRO << 4); - public UDPPacket buildRelayIntro(RemoteHostId alice, PeerState charlie, UDPPacketReader.RelayRequestReader request) { + public UDPPacket buildRelayIntro(RemoteHostId alice, PeerState charlie, UDPPacketReader.RelayRequestReader request) {// LINT -- Exporting non-public type through public API UDPPacket packet = UDPPacket.acquire(_context, false); byte data[] = packet.getPacket().getData(); Arrays.fill(data, 0, data.length, (byte)0x0); @@ -928,7 +929,7 @@ public class PacketBuilder { */ private static final byte PEER_RELAY_RESPONSE_FLAG_BYTE = (UDPPacket.PAYLOAD_TYPE_RELAY_RESPONSE << 4); - public UDPPacket buildRelayResponse(RemoteHostId alice, PeerState charlie, long nonce, SessionKey aliceIntroKey) { + public UDPPacket buildRelayResponse(RemoteHostId alice, PeerState charlie, long nonce, SessionKey aliceIntroKey) {// LINT -- Exporting non-public type through public API InetAddress aliceAddr = null; try { aliceAddr = InetAddress.getByAddress(alice.getIP()); diff --git a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java index 9e9cde1d34ceb5880fe2bfa2eec1497b05d9d65e..d32e8526dbef6f3b18625b95dc62f8de92f2f687 100644 --- a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java +++ b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java @@ -37,7 +37,7 @@ public class PacketHandler { private static final long GRACE_PERIOD = Router.CLOCK_FUDGE_FACTOR + 30*1000; - public PacketHandler(RouterContext ctx, UDPTransport transport, UDPEndpoint endpoint, EstablishmentManager establisher, InboundMessageFragments inbound, PeerTestManager testManager, IntroductionManager introManager) { + public PacketHandler(RouterContext ctx, UDPTransport transport, UDPEndpoint endpoint, EstablishmentManager establisher, InboundMessageFragments inbound, PeerTestManager testManager, IntroductionManager introManager) {// LINT -- Exporting non-public type through public API _context = ctx; _log = ctx.logManager().getLog(PacketHandler.class); _transport = transport; diff --git a/router/java/src/net/i2p/router/transport/udp/PeerState.java b/router/java/src/net/i2p/router/transport/udp/PeerState.java index f3cd1e269131b6ac9c6a0f347548fd4323b2b4ce..ff1f64f11b4e31915cc683ee1820d0ad6fae39c6 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerState.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerState.java @@ -74,13 +74,13 @@ public class PeerState { /** when did we last have a failed send (beginning of period) */ private long _lastFailedSendPeriod; /** list of messageIds (Long) that we have received but not yet sent */ - private List _currentACKs; + private final List _currentACKs; /** * list of the most recent messageIds (Long) that we have received and sent * an ACK for. We keep a few of these around to retransmit with _currentACKs, * hopefully saving some spurious retransmissions */ - private List _currentACKsResend; + private final List _currentACKsResend; /** when did we last send ACKs to the peer? */ private volatile long _lastACKSend; /** when did we decide we need to ACK to this peer? */ @@ -169,9 +169,9 @@ public class PeerState { private long _packetsReceived; /** list of InboundMessageState for active message */ - private Map _inboundMessages; + private final Map _inboundMessages; /** list of OutboundMessageState */ - private List _outboundMessages; + private final List _outboundMessages; /** which outbound message is currently being retransmitted */ private OutboundMessageState _retransmitter; @@ -802,6 +802,7 @@ public class PeerState { public long getMessageId() { return _msgId; } public boolean received(int fragmentNum) { return true; } public boolean receivedComplete() { return true; } + @Override public String toString() { return "Full ACK of " + _msgId; } } @@ -1010,7 +1011,7 @@ public class PeerState { return MAX_RTO; } - public RemoteHostId getRemoteHostId() { return _remoteHostId; } + public RemoteHostId getRemoteHostId() { return _remoteHostId; }// LINT -- Exporting non-public type through public API public int add(OutboundMessageState state) { if (_dead) { @@ -1560,6 +1561,7 @@ public class PeerState { } */ + @Override public String toString() { StringBuffer buf = new StringBuffer(64); buf.append(_remoteHostId.toString()); diff --git a/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java b/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java index 35c5511be4be4bc994ced8a0f24ba4408ad3b039..797cb8d4b7b14f1baf32515fb92f16103f8025a1 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java @@ -27,7 +27,7 @@ class PeerTestManager { private UDPTransport _transport; private PacketBuilder _packetBuilder; /** map of Long(nonce) to PeerTestState for tests currently in progress */ - private Map _activeTests; + private final Map _activeTests; /** current test we are running, or null */ private PeerTestState _currentTest; private boolean _currentTestComplete; diff --git a/router/java/src/net/i2p/router/transport/udp/PeerTestState.java b/router/java/src/net/i2p/router/transport/udp/PeerTestState.java index 57dc648d84c9981e8f11fb0a3b016c54032ad7c1..625bf648a7c9e1079ebf12c93ff18a6bcf8b300c 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerTestState.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerTestState.java @@ -96,6 +96,7 @@ class PeerTestState { public int getPacketsRelayed() { return _packetsRelayed; } public void incrementPacketsRelayed() { ++_packetsRelayed; } + @Override public synchronized String toString() { StringBuffer buf = new StringBuffer(512); buf.append("Role: "); diff --git a/router/java/src/net/i2p/router/transport/udp/RemoteHostId.java b/router/java/src/net/i2p/router/transport/udp/RemoteHostId.java index 117f8c5636003e52ca21d231f526f2733ce39a62..4bb2338f1f5e7e6ce86525936ea513cb7b3032b3 100644 --- a/router/java/src/net/i2p/router/transport/udp/RemoteHostId.java +++ b/router/java/src/net/i2p/router/transport/udp/RemoteHostId.java @@ -26,6 +26,7 @@ final class RemoteHostId { public int getPort() { return _port; } public byte[] getPeerHash() { return _peerHash; } + @Override public int hashCode() { int rv = 0; for (int i = 0; _ip != null && i < _ip.length; i++) @@ -36,6 +37,7 @@ final class RemoteHostId { return rv; } + @Override public boolean equals(Object obj) { if (obj == null) throw new NullPointerException("obj is null"); @@ -45,6 +47,7 @@ final class RemoteHostId { return (_port == id.getPort()) && DataHelper.eq(_ip, id.getIP()) && DataHelper.eq(_peerHash, id.getPeerHash()); } + @Override public String toString() { return toString(true); } public String toString(boolean includePort) { if (_ip != null) { diff --git a/router/java/src/net/i2p/router/transport/udp/TimedWeightedPriorityMessageQueue.java b/router/java/src/net/i2p/router/transport/udp/TimedWeightedPriorityMessageQueue.java index b28fb9101e0ff40ca58a1f5eac3d3c076b3facd9..9ff5a19503a040e9d4e198cf10bc9a475276940e 100644 --- a/router/java/src/net/i2p/router/transport/udp/TimedWeightedPriorityMessageQueue.java +++ b/router/java/src/net/i2p/router/transport/udp/TimedWeightedPriorityMessageQueue.java @@ -33,7 +33,7 @@ public class TimedWeightedPriorityMessageQueue implements MessageQueue, Outbound /** how many bytes total have been pulled off the given queue */ private long _bytesTransferred[]; /** lock to notify message enqueue/removal (and block for getNext()) */ - private Object _nextLock; + private final Object _nextLock; /** have we shut down or are we still alive? */ private boolean _alive; /** which queue should we pull out of next */ diff --git a/router/java/src/net/i2p/router/transport/udp/UDPAddress.java b/router/java/src/net/i2p/router/transport/udp/UDPAddress.java index df8b024f587126149b3da94063c9a9d02aa8394c..723817e0104b526a9e6fbcaf898c7d2c758d515d 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPAddress.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPAddress.java @@ -40,6 +40,7 @@ public class UDPAddress { parse(addr); } + @Override public String toString() { StringBuffer rv = new StringBuffer(64); if (_introHosts != null) { diff --git a/router/java/src/net/i2p/router/transport/udp/UDPFlooder.java b/router/java/src/net/i2p/router/transport/udp/UDPFlooder.java index dbcd8dfda4362dc8df28190e6c9d0a56d2e72a4f..14dfced396ccbe7d0afad19161158e4e03675d63 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPFlooder.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPFlooder.java @@ -18,7 +18,7 @@ class UDPFlooder implements Runnable { private RouterContext _context; private Log _log; private UDPTransport _transport; - private List _peers; + private final List _peers; private boolean _alive; private static final byte _floodData[] = new byte[4096]; @@ -37,9 +37,10 @@ class UDPFlooder implements Runnable { _peers.notifyAll(); } } + @SuppressWarnings("empty-statement") public void removePeer(PeerState peer) { synchronized (_peers) { - while (_peers.remove(peer)) + while (_peers.remove(peer)) // can this be written better? ;// loops until its empty _peers.notifyAll(); } diff --git a/router/java/src/net/i2p/router/transport/udp/UDPPacket.java b/router/java/src/net/i2p/router/transport/udp/UDPPacket.java index 46d8ae3c1490ca878f1e678e248b67b07db7d2f9..d6387f7c4e8407d0a4dec8738270f562140450dc 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPPacket.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPPacket.java @@ -129,7 +129,7 @@ public class UDPPacket { int getFragmentCount() { return _fragmentCount; } void setFragmentCount(int count) { _fragmentCount = count; } - public RemoteHostId getRemoteHost() { + public RemoteHostId getRemoteHost() {// LINT -- Exporting non-public type through public API if (_remoteHost == null) { long before = System.currentTimeMillis(); InetAddress addr = _packet.getAddress(); @@ -238,6 +238,7 @@ public class UDPPacket { /** how many times we tried to validate the packet */ int getValidateCount() { return _validateCount; } + @Override public String toString() { verifyNotReleased(); StringBuffer buf = new StringBuffer(64); diff --git a/router/java/src/net/i2p/router/transport/udp/UDPPacketReader.java b/router/java/src/net/i2p/router/transport/udp/UDPPacketReader.java index 159c21ae6042c04ae3f5444d471daf205795059c..5bff1789d77d92a016fa8433792fb05add487cc7 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPPacketReader.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPPacketReader.java @@ -105,6 +105,7 @@ public class UDPPacketReader { public RelayIntroReader getRelayIntroReader() { return _relayIntroReader; } public RelayResponseReader getRelayResponseReader() { return _relayResponseReader; } + @Override public String toString() { switch (readPayloadType()) { case UDPPacket.PAYLOAD_TYPE_DATA: @@ -398,6 +399,7 @@ public class UDPPacketReader { return ((_message[flagOffset] & flag) != 0); } + @Override public String toString() { StringBuffer buf = new StringBuffer(256); long msAgo = _context.clock().now() - readTimestamp()*1000; @@ -502,6 +504,7 @@ public class UDPPacketReader { int flagNum = fragmentNum % 7; return (_message[byteNum] & (1 << flagNum)) != 0x0; } + @Override public String toString() { StringBuffer buf = new StringBuffer(64); buf.append("Read partial ACK of "); diff --git a/router/java/src/net/i2p/router/transport/udp/UDPReceiver.java b/router/java/src/net/i2p/router/transport/udp/UDPReceiver.java index 3535484c9f4d8df1f13b6e546d96b7f13e8443de..72fdbbf0e45aba4de2b2d66855e277dcda7a17a4 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPReceiver.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPReceiver.java @@ -25,7 +25,7 @@ public class UDPReceiver { private Log _log; private DatagramSocket _socket; private String _name; - private List _inboundQueue; + private final List _inboundQueue; private boolean _keepRunning; private Runner _runner; private UDPTransport _transport; diff --git a/router/java/src/net/i2p/router/transport/udp/UDPSender.java b/router/java/src/net/i2p/router/transport/udp/UDPSender.java index 141b8789282d32db7f44e09aa8e732a2551ead4c..dbc78e8a01c61e262568be6566d69a176108daee 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPSender.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPSender.java @@ -20,7 +20,7 @@ public class UDPSender { private Log _log; private DatagramSocket _socket; private String _name; - private List _outboundQueue; + private final List _outboundQueue; private boolean _keepRunning; private Runner _runner; diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java index 871af78ee4bb634e1bc98bc4196f68b0b99c638b..45de86244368b343da3f0f6903f1a94ab6ea4ca1 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -40,13 +40,13 @@ import net.i2p.util.SimpleTimer; * */ public class UDPTransport extends TransportImpl implements TimedWeightedPriorityMessageQueue.FailedListener { - private RouterContext _context; + private RouterContext _context; // LINT -- field hides a field private Log _log; private UDPEndpoint _endpoint; /** Peer (Hash) to PeerState */ - private Map _peersByIdent; + private final Map _peersByIdent; /** RemoteHostId to PeerState */ - private Map _peersByRemoteHost; + private final Map _peersByRemoteHost; private PacketHandler _handler; private EstablishmentManager _establisher; private MessageQueue _outboundMessages; @@ -90,7 +90,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private TransportBid _transientFail; /** list of RemoteHostId for peers whose packets we want to drop outright */ - private List _dropList; + private final List _dropList; private int _expireTimeout; @@ -437,7 +437,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority * get the state for the peer at the given remote host/port, or null * if no state exists */ - public PeerState getPeerState(RemoteHostId hostInfo) { + public PeerState getPeerState(RemoteHostId hostInfo) { // LINT -- Exporting non-public type through public API synchronized (_peersByRemoteHost) { return (PeerState)_peersByRemoteHost.get(hostInfo); } @@ -597,6 +597,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority } ***/ + @Override public void messageReceived(I2NPMessage inMsg, RouterIdentity remoteIdent, Hash remoteIdentHash, long msToReceive, int bytesReceived) { if (inMsg.getType() == DatabaseStoreMessage.MESSAGE_TYPE) { DatabaseStoreMessage dsm = (DatabaseStoreMessage)inMsg; @@ -673,7 +674,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority } } - public boolean isInDropList(RemoteHostId peer) { synchronized (_dropList) { return _dropList.contains(peer); } } + public boolean isInDropList(RemoteHostId peer) { synchronized (_dropList) { return _dropList.contains(peer); } }// LINT -- Exporting non-public type through public API void dropPeer(Hash peer, boolean shouldShitlist, String why) { PeerState state = getPeerState(peer); @@ -935,6 +936,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static final int MIN_EXPIRE_TIMEOUT = 10*60*1000; public String getStyle() { return STYLE; } + @Override public void send(OutNetMessage msg) { if (msg == null) return; if (msg.getTarget() == null) return; @@ -1242,6 +1244,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority super.afterSend(m, true); } + @Override public int countActivePeers() { long now = _context.clock().now(); int active = 0; @@ -1258,6 +1261,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority return active; } + @Override public int countActiveSendPeers() { long now = _context.clock().now(); int active = 0; @@ -1274,6 +1278,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority return active; } + @Override public boolean isEstablished(Hash dest) { return getPeerState(dest) != null; } @@ -1284,6 +1289,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority } } + @Override public boolean haveCapacity() { synchronized (_peersByIdent) { return _peersByIdent.size() < getMaxConnections() * 4 / 5; @@ -1294,6 +1300,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority * Return our peer clock skews on this transport. * Vector composed of Long, each element representing a peer skew in seconds. */ + @Override public Vector getClockSkews() { Vector skews = new Vector(); @@ -1419,6 +1426,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class IdleInComparator extends PeerComparator { private static final IdleInComparator _instance = new IdleInComparator(); public static final IdleInComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = r.getLastReceiveTime() - l.getLastReceiveTime(); if (rv == 0) // fallback on alpha @@ -1430,6 +1438,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class IdleOutComparator extends PeerComparator { private static final IdleOutComparator _instance = new IdleOutComparator(); public static final IdleOutComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = r.getLastSendTime() - l.getLastSendTime(); if (rv == 0) // fallback on alpha @@ -1441,6 +1450,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class RateInComparator extends PeerComparator { private static final RateInComparator _instance = new RateInComparator(); public static final RateInComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = l.getReceiveBps() - r.getReceiveBps(); if (rv == 0) // fallback on alpha @@ -1452,6 +1462,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class RateOutComparator extends PeerComparator { private static final RateOutComparator _instance = new RateOutComparator(); public static final RateOutComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = l.getSendBps() - r.getSendBps(); if (rv == 0) // fallback on alpha @@ -1463,6 +1474,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class UptimeComparator extends PeerComparator { private static final UptimeComparator _instance = new UptimeComparator(); public static final UptimeComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = r.getKeyEstablishedTime() - l.getKeyEstablishedTime(); if (rv == 0) // fallback on alpha @@ -1474,6 +1486,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class SkewComparator extends PeerComparator { private static final SkewComparator _instance = new SkewComparator(); public static final SkewComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = Math.abs(l.getClockSkew()) - Math.abs(r.getClockSkew()); if (rv == 0) // fallback on alpha @@ -1485,6 +1498,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class CwndComparator extends PeerComparator { private static final CwndComparator _instance = new CwndComparator(); public static final CwndComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = l.getSendWindowBytes() - r.getSendWindowBytes(); if (rv == 0) // fallback on alpha @@ -1496,6 +1510,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class SsthreshComparator extends PeerComparator { private static final SsthreshComparator _instance = new SsthreshComparator(); public static final SsthreshComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = l.getSlowStartThreshold() - r.getSlowStartThreshold(); if (rv == 0) // fallback on alpha @@ -1507,6 +1522,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class RTTComparator extends PeerComparator { private static final RTTComparator _instance = new RTTComparator(); public static final RTTComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = l.getRTT() - r.getRTT(); if (rv == 0) // fallback on alpha @@ -1518,6 +1534,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class DevComparator extends PeerComparator { private static final DevComparator _instance = new DevComparator(); public static final DevComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = l.getRTTDeviation() - r.getRTTDeviation(); if (rv == 0) // fallback on alpha @@ -1529,6 +1546,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class RTOComparator extends PeerComparator { private static final RTOComparator _instance = new RTOComparator(); public static final RTOComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = l.getRTO() - r.getRTO(); if (rv == 0) // fallback on alpha @@ -1540,6 +1558,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class MTUComparator extends PeerComparator { private static final MTUComparator _instance = new MTUComparator(); public static final MTUComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = l.getMTU() - r.getMTU(); if (rv == 0) // fallback on alpha @@ -1551,6 +1570,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class SendCountComparator extends PeerComparator { private static final SendCountComparator _instance = new SendCountComparator(); public static final SendCountComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = l.getPacketsTransmitted() - r.getPacketsTransmitted(); if (rv == 0) // fallback on alpha @@ -1562,6 +1582,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class RecvCountComparator extends PeerComparator { private static final RecvCountComparator _instance = new RecvCountComparator(); public static final RecvCountComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = l.getPacketsReceived() - r.getPacketsReceived(); if (rv == 0) // fallback on alpha @@ -1573,6 +1594,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class ResendComparator extends PeerComparator { private static final ResendComparator _instance = new ResendComparator(); public static final ResendComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = l.getPacketsRetransmitted() - r.getPacketsRetransmitted(); if (rv == 0) // fallback on alpha @@ -1584,6 +1606,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority private static class DupComparator extends PeerComparator { private static final DupComparator _instance = new DupComparator(); public static final DupComparator instance() { return _instance; } + @Override protected int compare(PeerState l, PeerState r) { long rv = l.getPacketsReceivedDuplicate() - r.getPacketsReceivedDuplicate(); if (rv == 0) // fallback on alpha @@ -1628,6 +1651,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority //public void renderStatusHTML(Writer out) throws IOException { renderStatusHTML(out, 0); } public void renderStatusHTML(Writer out, int sortFlags) throws IOException {} + @Override public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException { TreeSet peers = new TreeSet(getComparator(sortFlags)); synchronized (_peersByIdent) { @@ -1970,12 +1994,14 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority */ private class SharedBid extends TransportBid { public SharedBid(int ms) { super(); setLatencyMs(ms); } + @Override public Transport getTransport() { return UDPTransport.this; } + @Override public String toString() { return "UDP bid @ " + getLatencyMs(); } } private class ExpirePeerEvent implements SimpleTimer.TimedEvent { - private List _expirePeers; + private final List _expirePeers; private List _expireBuffer; private boolean _alive; public ExpirePeerEvent() { @@ -2102,11 +2128,12 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority return _reachabilityStatus; } + @Override public void recheckReachability() { _testEvent.runTest(); } - public PeerState pickTestPeer(RemoteHostId dontInclude) { + public PeerState pickTestPeer(RemoteHostId dontInclude) {// LINT -- Exporting non-public type through public API List peers = null; synchronized (_peersByIdent) { peers = new ArrayList(_peersByIdent.values()); diff --git a/router/java/src/net/i2p/router/tunnel/BatchedPreprocessor.java b/router/java/src/net/i2p/router/tunnel/BatchedPreprocessor.java index 6d2e7b7396a652cfefb8c851a1e6eca02f726b25..2de7868dbfa2b21dca5a24cda9c75fafede5f0e2 100644 --- a/router/java/src/net/i2p/router/tunnel/BatchedPreprocessor.java +++ b/router/java/src/net/i2p/router/tunnel/BatchedPreprocessor.java @@ -49,6 +49,7 @@ public class BatchedPreprocessor extends TrivialPreprocessor { private static final int FORCE_BATCH_FLUSH = 50; /** how long do we want to wait before flushing */ + @Override public long getDelayAmount() { return getDelayAmount(true); } private long getDelayAmount(boolean shouldStat) { long rv = -1; @@ -62,6 +63,7 @@ public class BatchedPreprocessor extends TrivialPreprocessor { return rv; } + @Override public boolean preprocessQueue(List pending, TunnelGateway.Sender sender, TunnelGateway.Receiver rec) { StringBuffer timingBuf = null; if (_log.shouldLog(Log.DEBUG)) { diff --git a/router/java/src/net/i2p/router/tunnel/BatchedRouterPreprocessor.java b/router/java/src/net/i2p/router/tunnel/BatchedRouterPreprocessor.java index 0be137b4512e190b0e52bcddcee95f111e7dc499..2e5e988855b5d05b072a72ae15fc28d0e0d4d356 100644 --- a/router/java/src/net/i2p/router/tunnel/BatchedRouterPreprocessor.java +++ b/router/java/src/net/i2p/router/tunnel/BatchedRouterPreprocessor.java @@ -57,6 +57,7 @@ public class BatchedRouterPreprocessor extends BatchedPreprocessor { } /** how long should we wait before flushing */ + @Override protected long getSendDelay() { String freq = null; if (_config != null) { @@ -77,6 +78,7 @@ public class BatchedRouterPreprocessor extends BatchedPreprocessor { return DEFAULT_BATCH_FREQUENCY; } + @Override protected void notePreprocessing(long messageId, int numFragments, int totalLength, List messageIds, String msg) { if (_config != null) _routerContext.messageHistory().fragmentMessage(messageId, numFragments, totalLength, messageIds, _config, msg); diff --git a/router/java/src/net/i2p/router/tunnel/FragmentHandler.java b/router/java/src/net/i2p/router/tunnel/FragmentHandler.java index 99b66c0c8b805e6f1ed1e3027539c33fa97036b0..43e1d13144de93911a3c84eccdb6c1fac94a16ff 100644 --- a/router/java/src/net/i2p/router/tunnel/FragmentHandler.java +++ b/router/java/src/net/i2p/router/tunnel/FragmentHandler.java @@ -26,7 +26,7 @@ import net.i2p.util.SimpleTimer; public class FragmentHandler { private I2PAppContext _context; private Log _log; - private Map _fragmentedMessages; + private final Map _fragmentedMessages; private DefragmentedReceiver _receiver; private int _completed; private int _failed; @@ -106,7 +106,18 @@ public class FragmentHandler { if (_log.shouldLog(Log.ERROR)) _log.error("Corrupt fragment received: offset = " + offset, e); _context.statManager().addRateData("tunnel.corruptMessage", 1, 1); - throw e; + // java.lang.IllegalStateException: wtf, don't get the completed size when we're not complete - null fragment i=0 of 1 + // at net.i2p.router.tunnel.FragmentedMessage.getCompleteSize(FragmentedMessage.java:194) + // at net.i2p.router.tunnel.FragmentedMessage.toByteArray(FragmentedMessage.java:223) + // at net.i2p.router.tunnel.FragmentHandler.receiveComplete(FragmentHandler.java:380) + // at net.i2p.router.tunnel.FragmentHandler.receiveSubsequentFragment(FragmentHandler.java:353) + // at net.i2p.router.tunnel.FragmentHandler.receiveFragment(FragmentHandler.java:208) + // at net.i2p.router.tunnel.FragmentHandler.receiveTunnelMessage(FragmentHandler.java:92) + // ... + // still trying to find root cause + // let's limit the damage here and skip the: + // .transport.udp.MessageReceiver: b0rked receiving a message.. wazza huzza hmm? + //throw e; } finally { // each of the FragmentedMessages populated make a copy out of the // payload, which they release separately, so we can release diff --git a/router/java/src/net/i2p/router/tunnel/FragmentedMessage.java b/router/java/src/net/i2p/router/tunnel/FragmentedMessage.java index b0203f540d117ee52bcc12e41d422b1bb5d2c8a8..94e2c8c2487ccaf00cbe9b79f0de66f6e5d9d9cf 100644 --- a/router/java/src/net/i2p/router/tunnel/FragmentedMessage.java +++ b/router/java/src/net/i2p/router/tunnel/FragmentedMessage.java @@ -273,6 +273,7 @@ public class FragmentedMessage { } } + @Override public String toString() { StringBuffer buf = new StringBuffer(128); buf.append("Fragments for ").append(_messageId).append(": "); diff --git a/router/java/src/net/i2p/router/tunnel/HashSetIVValidator.java b/router/java/src/net/i2p/router/tunnel/HashSetIVValidator.java index aea18dc3f645ddead8f2c01d85b061cafaca9329..c9241fccef255459fb89f16c3c3be46fe3cb8fac 100644 --- a/router/java/src/net/i2p/router/tunnel/HashSetIVValidator.java +++ b/router/java/src/net/i2p/router/tunnel/HashSetIVValidator.java @@ -9,7 +9,7 @@ import net.i2p.data.DataHelper; * waste lots of RAM */ class HashSetIVValidator implements IVValidator { - private HashSet _received; + private final HashSet _received; public HashSetIVValidator() { _received = new HashSet(); diff --git a/router/java/src/net/i2p/router/tunnel/HopConfig.java b/router/java/src/net/i2p/router/tunnel/HopConfig.java index 740cf9025ce502517c9156cedb8ad782150a2fd7..ab0c32a3f35a455c8650d1bb8a02d0a57497e3aa 100644 --- a/router/java/src/net/i2p/router/tunnel/HopConfig.java +++ b/router/java/src/net/i2p/router/tunnel/HopConfig.java @@ -135,6 +135,7 @@ public class HopConfig { return rv; } + @Override public String toString() { StringBuffer buf = new StringBuffer(64); if (_receiveTunnelId != null) { diff --git a/router/java/src/net/i2p/router/tunnel/InboundMessageDistributor.java b/router/java/src/net/i2p/router/tunnel/InboundMessageDistributor.java index c5c46c365799273b468470514009162026740fdb..b1b03fb22fb3e59bcafb2ff3784649778be7c20f 100644 --- a/router/java/src/net/i2p/router/tunnel/InboundMessageDistributor.java +++ b/router/java/src/net/i2p/router/tunnel/InboundMessageDistributor.java @@ -10,7 +10,6 @@ import net.i2p.data.i2np.DeliveryStatusMessage; import net.i2p.data.i2np.GarlicMessage; import net.i2p.data.i2np.I2NPMessage; import net.i2p.data.i2np.TunnelBuildReplyMessage; -import net.i2p.data.i2np.TunnelGatewayMessage; import net.i2p.router.ClientMessage; import net.i2p.router.RouterContext; import net.i2p.router.TunnelInfo; diff --git a/router/java/src/net/i2p/router/tunnel/PumpedTunnelGateway.java b/router/java/src/net/i2p/router/tunnel/PumpedTunnelGateway.java index a2cac90bb9a8f9b7ae350e98bbfc5c728add4538..9364092df5db80e302427e905300879a4de2bfe3 100644 --- a/router/java/src/net/i2p/router/tunnel/PumpedTunnelGateway.java +++ b/router/java/src/net/i2p/router/tunnel/PumpedTunnelGateway.java @@ -32,7 +32,7 @@ import net.i2p.util.Log; * */ public class PumpedTunnelGateway extends TunnelGateway { - private List _prequeue; + private final List _prequeue; private TunnelGatewayPumper _pumper; /** @@ -58,6 +58,7 @@ public class PumpedTunnelGateway extends TunnelGateway { * @param toRouter router to send to after the endpoint (or null for endpoint processing) * @param toTunnel tunnel to send to after the endpoint (or null for endpoint or router processing) */ + @Override public void add(I2NPMessage msg, Hash toRouter, TunnelId toTunnel) { _messagesSent++; Pending cur = new PendingImpl(msg, toRouter, toTunnel); diff --git a/router/java/src/net/i2p/router/tunnel/RouterFragmentHandler.java b/router/java/src/net/i2p/router/tunnel/RouterFragmentHandler.java index 7caa3271e6263f3c36d5619260b00cf2b0f98008..acb4231d27cf6989435576bf33deb744af384268 100644 --- a/router/java/src/net/i2p/router/tunnel/RouterFragmentHandler.java +++ b/router/java/src/net/i2p/router/tunnel/RouterFragmentHandler.java @@ -16,16 +16,19 @@ public class RouterFragmentHandler extends FragmentHandler { _log = context.logManager().getLog(RouterFragmentHandler.class); } + @Override protected void noteReception(long messageId, int fragmentId, Object status) { if (_log.shouldLog(Log.INFO)) _log.info("Received fragment " + fragmentId + " for message " + messageId + ": " + status); _routerContext.messageHistory().receiveTunnelFragment(messageId, fragmentId, status); } + @Override protected void noteCompletion(long messageId) { if (_log.shouldLog(Log.INFO)) _log.info("Received complete message " + messageId); _routerContext.messageHistory().receiveTunnelFragmentComplete(messageId); } + @Override protected void noteFailure(long messageId, String status) { if (_log.shouldLog(Log.INFO)) _log.info("Dropped message " + messageId + ": " + status); diff --git a/router/java/src/net/i2p/router/tunnel/TunnelCreatorConfig.java b/router/java/src/net/i2p/router/tunnel/TunnelCreatorConfig.java index 83f5fbf94e0e6418f2556989a9079fd6b480f2b4..72dccf45c19a9775aaff444a93baeb70cea64b11 100644 --- a/router/java/src/net/i2p/router/tunnel/TunnelCreatorConfig.java +++ b/router/java/src/net/i2p/router/tunnel/TunnelCreatorConfig.java @@ -163,6 +163,7 @@ public class TunnelCreatorConfig implements TunnelInfo { _failures = 0; } + @Override public String toString() { // H0:1235-->H1:2345-->H2:2345 StringBuffer buf = new StringBuffer(128); diff --git a/router/java/src/net/i2p/router/tunnel/TunnelGateway.java b/router/java/src/net/i2p/router/tunnel/TunnelGateway.java index a9ed0cc1e76df912be1ef39f6c418cb838be4e93..077a43b7de30c3886c793ac5c0b727ded695773f 100644 --- a/router/java/src/net/i2p/router/tunnel/TunnelGateway.java +++ b/router/java/src/net/i2p/router/tunnel/TunnelGateway.java @@ -36,13 +36,13 @@ import net.i2p.util.SimpleTimer; public class TunnelGateway { protected I2PAppContext _context; protected Log _log; - protected List _queue; + protected final List _queue; protected QueuePreprocessor _preprocessor; protected Sender _sender; protected Receiver _receiver; protected long _lastFlush; protected int _flushFrequency; - protected DelayedFlush _delayedFlush; + protected DelayedFlush _delayedFlush;// LINT -- Exporting non-public type through public API protected int _messagesSent; /** @@ -236,6 +236,7 @@ public class TunnelGateway { super(message, toRouter, toTunnel, _context.clock().now()); } + @Override public String toString() { StringBuffer buf = new StringBuffer(64); buf.append("Message ").append(_messageId).append(" on "); @@ -257,6 +258,7 @@ public class TunnelGateway { return buf.toString(); } + @Override public long getLifetime() { return _context.clock().now()-_created; } } diff --git a/router/java/src/net/i2p/router/tunnel/TunnelGatewayPumper.java b/router/java/src/net/i2p/router/tunnel/TunnelGatewayPumper.java index 7e808199dea1f2b49cee2e3aaaa9661e2ad1ad3e..b840dad287bb154f7854697ed292dc95aafd62f0 100644 --- a/router/java/src/net/i2p/router/tunnel/TunnelGatewayPumper.java +++ b/router/java/src/net/i2p/router/tunnel/TunnelGatewayPumper.java @@ -14,7 +14,7 @@ import net.i2p.util.Log; public class TunnelGatewayPumper implements Runnable { private RouterContext _context; private Log _log; - private List _wantsPumping; + private final List _wantsPumping; private boolean _stop; /** Creates a new instance of TunnelGatewayPumper */ diff --git a/router/java/src/net/i2p/router/tunnel/TunnelGatewayZeroHop.java b/router/java/src/net/i2p/router/tunnel/TunnelGatewayZeroHop.java index 1abceb9f25e85afccfd3a76e0ca77b67da205c04..aefe9670decd0f42b5b2b88b14b88b6aac12948f 100644 --- a/router/java/src/net/i2p/router/tunnel/TunnelGatewayZeroHop.java +++ b/router/java/src/net/i2p/router/tunnel/TunnelGatewayZeroHop.java @@ -12,8 +12,8 @@ import net.i2p.util.Log; * */ public class TunnelGatewayZeroHop extends TunnelGateway { - private RouterContext _context; - private Log _log; + private RouterContext _context; // LINT -- field hides a field + private Log _log; // LINT -- field hides a field private TunnelCreatorConfig _config; private OutboundMessageDistributor _outDistributor; private InboundMessageDistributor _inDistributor; @@ -37,6 +37,7 @@ public class TunnelGatewayZeroHop extends TunnelGateway { * * @param msg message received to be sent through the tunnel */ + @Override public void add(TunnelGatewayMessage msg) { add(msg.getMessage(), null, null); } @@ -50,6 +51,7 @@ public class TunnelGatewayZeroHop extends TunnelGateway { * @param toRouter router to send to after the endpoint (or null for endpoint processing) * @param toTunnel tunnel to send to after the endpoint (or null for endpoint or router processing) */ + @Override public void add(I2NPMessage msg, Hash toRouter, TunnelId toTunnel) { if (_log.shouldLog(Log.DEBUG)) _log.debug("zero hop gateway: distribute " + (_config.isInbound() ? "inbound " : " outbound ") diff --git a/router/java/src/net/i2p/router/tunnel/TunnelParticipant.java b/router/java/src/net/i2p/router/tunnel/TunnelParticipant.java index 5fc8708572147fdf31634d91341c94c7a29c07a6..5e4a92641bb4e5adf99cb72851be12f0790f59ed 100644 --- a/router/java/src/net/i2p/router/tunnel/TunnelParticipant.java +++ b/router/java/src/net/i2p/router/tunnel/TunnelParticipant.java @@ -218,6 +218,7 @@ public class TunnelParticipant { } } + @Override public String toString() { if (_config != null) { StringBuffer buf = new StringBuffer(64); diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java b/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java index 06a66635432e51e055e3765a1360bfcb1686c888..05b53fbf9b4bc9874ed5d497fd7b3c9978d2b11d 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java +++ b/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java @@ -21,11 +21,12 @@ import net.i2p.util.Log; * */ class BuildExecutor implements Runnable { + private final List _recentBuildIds = new ArrayList(100); private RouterContext _context; private Log _log; private TunnelPoolManager _manager; /** list of TunnelCreatorConfig elements of tunnels currently being built */ - private List _currentlyBuilding; + private final List _currentlyBuilding; private boolean _isRunning; private BuildHandler _handler; private boolean _repoll; @@ -50,7 +51,7 @@ class BuildExecutor implements Runnable { // Get stat manager, get recognized bandwidth tiers StatManager statMgr = _context.statManager(); - String bwTiers = _context.router().getRouterInfo().BW_CAPABILITY_CHARS; + String bwTiers = _context.router().getRouterInfo().BW_CAPABILITY_CHARS; // LINT -- Accessing static field "BW_CAPABILITY_CHARS" // For each bandwidth tier, create tunnel build agree/reject/expire stats for (int i = 0; i < bwTiers.length(); i++) { String bwTier = String.valueOf(bwTiers.charAt(i)); @@ -423,7 +424,6 @@ class BuildExecutor implements Runnable { } } - private List _recentBuildIds = new ArrayList(100); public boolean wasRecentlyBuilding(long replyId) { synchronized (_recentBuildIds) { return _recentBuildIds.contains(new Long(replyId)); diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java index 0699d3ff4d04b0df98485f266c3c08f738161d00..38350544e68ac803fb74bf3222c9cc25b737f78b 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java +++ b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java @@ -39,11 +39,11 @@ class BuildHandler { private Job _buildMessageHandlerJob; private Job _buildReplyMessageHandlerJob; /** list of BuildMessageState, oldest first */ - private List _inboundBuildMessages; + private final List _inboundBuildMessages; /** list of BuildReplyMessageState, oldest first */ - private List _inboundBuildReplyMessages; + private final List _inboundBuildReplyMessages; /** list of BuildEndMessageState, oldest first */ - private List _inboundBuildEndMessages; + private final List _inboundBuildEndMessages; private BuildMessageProcessor _processor; public BuildHandler(RouterContext ctx, BuildExecutor exec) { @@ -607,7 +607,7 @@ class BuildHandler { // send it to the reply tunnel on the reply peer within a new TunnelBuildReplyMessage // (enough layers jrandom?) TunnelBuildReplyMessage replyMsg = new TunnelBuildReplyMessage(_context); - for (int i = 0; i < state.msg.RECORD_COUNT; i++) + for (int i = 0; i < state.msg.RECORD_COUNT; i++) // LINT -- Accessing Static field "RECORD_COUNT" replyMsg.setRecord(i, state.msg.getRecord(i)); replyMsg.setUniqueId(req.readReplyMessageId()); replyMsg.setMessageExpiration(_context.clock().now() + 10*1000); diff --git a/router/java/src/net/i2p/router/tunnel/pool/PooledTunnelCreatorConfig.java b/router/java/src/net/i2p/router/tunnel/pool/PooledTunnelCreatorConfig.java index 76f2c3c256abd35451ff8072a2a986fd0bd30062..3cc4906ea93a3c1ef680519f218d0eb50a9effbf 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/PooledTunnelCreatorConfig.java +++ b/router/java/src/net/i2p/router/tunnel/pool/PooledTunnelCreatorConfig.java @@ -31,6 +31,7 @@ public class PooledTunnelCreatorConfig extends TunnelCreatorConfig { } // calls TestJob + @Override public void testSuccessful(int ms) { if (_testJob != null) _testJob.testSuccessful(ms); @@ -47,6 +48,7 @@ public class PooledTunnelCreatorConfig extends TunnelCreatorConfig { /** * The tunnel failed a test, so (maybe) stop using it */ + @Override public boolean tunnelFailed() { boolean rv = super.tunnelFailed(); if (!rv) { @@ -60,6 +62,7 @@ public class PooledTunnelCreatorConfig extends TunnelCreatorConfig { return rv; } + @Override public Properties getOptions() { if (_pool == null) return null; return _pool.getSettings().getUnknownOptions(); @@ -75,7 +78,8 @@ public class PooledTunnelCreatorConfig extends TunnelCreatorConfig { } public TunnelPool getTunnelPool() { return _pool; } - public void setTestJob(TestJob job) { _testJob = job; } + + public void setTestJob(TestJob job) { _testJob = job; } // LINT -- Exporting non-public type through public API public void setExpireJob(Job job) { /* _expireJob = job; */ } // Fix memory leaks caused by references if you need to use pairedTunnel diff --git a/router/java/src/net/i2p/router/tunnel/pool/TestJob.java b/router/java/src/net/i2p/router/tunnel/pool/TestJob.java index b81178bdf75b8baf81ff43a2c075361552bef69d..24b379543e6cc58ea5039e042f557440e72eb138 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TestJob.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TestJob.java @@ -250,6 +250,7 @@ class TestJob extends JobImpl { return false; } + @Override public String toString() { StringBuffer rv = new StringBuffer(64); rv.append("Testing tunnel ").append(_cfg.toString()).append(" waiting for "); @@ -281,6 +282,7 @@ class TestJob extends JobImpl { _successTime = getContext().clock().now() - ((DeliveryStatusMessage)message).getArrival(); } + @Override public String toString() { StringBuffer rv = new StringBuffer(64); rv.append("Testing tunnel ").append(_cfg.toString()); @@ -306,6 +308,7 @@ class TestJob extends JobImpl { testFailed(getContext().clock().now() - _started); } + @Override public String toString() { StringBuffer rv = new StringBuffer(64); rv.append("Testing tunnel ").append(_cfg.toString()); diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java index 699a8be9f1468e57b09e33c235d589ff35247333..8ce5859df0877bcfb4b5c096fb74ff9b0e9aacd4 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java @@ -25,10 +25,11 @@ import net.i2p.util.Log; * */ public class TunnelPool { + private final List _inProgress = new ArrayList(); private RouterContext _context; private Log _log; private TunnelPoolSettings _settings; - private ArrayList<TunnelInfo> _tunnels; + private final ArrayList<TunnelInfo> _tunnels; private TunnelPeerSelector _peerSelector; private TunnelPoolManager _manager; private boolean _alive; @@ -64,6 +65,9 @@ public class TunnelPool { } public void startup() { + synchronized (_inProgress) { + _inProgress.clear(); + } _alive = true; _started = System.currentTimeMillis(); _lastRateUpdate = _started; @@ -90,6 +94,9 @@ public class TunnelPool { _lastSelectionPeriod = 0; _lastSelected = null; _context.statManager().removeRateStat(_rateName); + synchronized (_inProgress) { + _inProgress.clear(); + } } TunnelPoolManager getManager() { return _manager; } @@ -292,7 +299,9 @@ public class TunnelPool { int remaining = 0; LeaseSet ls = null; synchronized (_tunnels) { - _tunnels.remove(info); + boolean removed = _tunnels.remove(info); + if (!removed) + return; if (_settings.isInbound() && (_settings.getDestination() != null) ) ls = locked_buildNewLeaseSet(); remaining = _tunnels.size(); @@ -333,12 +342,15 @@ public class TunnelPool { } } + /** This may be called multiple times from TestJob */ public void tunnelFailed(PooledTunnelCreatorConfig cfg) { if (_log.shouldLog(Log.WARN)) _log.warn(toString() + ": Tunnel failed: " + cfg); LeaseSet ls = null; synchronized (_tunnels) { - _tunnels.remove(cfg); + boolean removed = _tunnels.remove(cfg); + if (!removed) + return; if (_settings.isInbound() && (_settings.getDestination() != null) ) ls = locked_buildNewLeaseSet(); if (_lastSelected == cfg) { @@ -464,7 +476,7 @@ public class TunnelPool { if (!_alive) return null; - int wanted = _settings.getQuantity(); + int wanted = Math.min(_settings.getQuantity(), LeaseSet.MAX_LEASES); if (_tunnels.size() < wanted) { if (_log.shouldLog(Log.WARN)) _log.warn(toString() + ": Not enough tunnels (" + _tunnels.size() + ", wanted " + wanted + ")"); @@ -866,13 +878,13 @@ public class TunnelPool { return cfg; } - private List _inProgress = new ArrayList(); void buildComplete(PooledTunnelCreatorConfig cfg) { synchronized (_inProgress) { _inProgress.remove(cfg); } cfg.setTunnelPool(this); //_manager.buildComplete(cfg); } + @Override public String toString() { if (_settings.isExploratory()) { if (_settings.isInbound()) diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java index acbb9345db9795ff85d8751f30e7ef42eed18b70..852ee28ff3ea3b502211a2d95917791d25cea81d 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java @@ -38,9 +38,9 @@ public class TunnelPoolManager implements TunnelManagerFacade { private RouterContext _context; private Log _log; /** Hash (destination) to TunnelPool */ - private Map _clientInboundPools; + private final Map _clientInboundPools; /** Hash (destination) to TunnelPool */ - private Map _clientOutboundPools; + private final Map _clientOutboundPools; private TunnelPool _inboundExploratory; private TunnelPool _outboundExploratory; private LoadTestManager _loadTestManager;