diff --git a/README.txt b/README.txt
new file mode 100644
index 000000000..49a62ee5b
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,31 @@
+Prerequisites to build from source:
+ Java SDK (preferably Sun) 1.5.0 or higher (1.6 recommended)
+ Apache Ant 1.7.0 or higher
+
+To build:
+ ant pkg
+ Run 'ant' with no arguments to see other build options.
+ See http://www.i2p2.de/download.html for installation instructions.
+
+Documentation:
+ http://www.i2p2.de/
+ API: run 'ant javadoc' then start at build/javadoc/index.html
+
+Latest release:
+ http://www.i2p2.de/download.html
+
+To get development branch from source control:
+ http://www.i2p2.de/newdevelopers.html
+
+FAQ:
+ http://www.i2p2.de/faq.html
+
+Need help?
+ IRC irc.freenode.net #i2p
+ http://forum.i2p2.de/
+
+Licenses:
+ http://www.i2p2.de/licenses.html
+ Also http://localhost:7657/help.jsp
+ Also see licenses for the individual bundled apps in apps/*
+
diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
index f014580ec..26ed5860f 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
@@ -24,6 +24,7 @@ import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.util.EepGet;
import net.i2p.util.Log;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@@ -183,7 +184,7 @@ public class I2PSnarkUtil {
synchronized (_shitlist) {
_shitlist.add(dest);
}
- SimpleTimer.getInstance().addEvent(new Unshitlist(dest), 10*60*1000);
+ SimpleScheduler.getInstance().addEvent(new Unshitlist(dest), 10*60*1000);
throw new IOException("Unable to reach the peer " + peer + ": " + ie.getMessage());
}
}
diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java b/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java
index 8fed9577a..1a53c342f 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java
@@ -28,6 +28,7 @@ import java.util.List;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
class PeerConnectionOut implements Runnable
@@ -215,7 +216,7 @@ class PeerConnectionOut implements Runnable
private void addMessage(Message m)
{
if (m.type == Message.PIECE)
- SimpleTimer.getInstance().addEvent(new RemoveTooSlow(m), SEND_TIMEOUT);
+ SimpleScheduler.getInstance().addEvent(new RemoveTooSlow(m), SEND_TIMEOUT);
synchronized(sendQueue)
{
sendQueue.add(m);
diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java
index 1b4feee75..054b58262 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java
@@ -60,7 +60,7 @@ class PeerState
// If we have te resend outstanding requests (true after we got choked).
private boolean resend = false;
- private final static int MAX_PIPELINE = 2; // this is for outbound requests
+ private final static int MAX_PIPELINE = 3; // 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
private final static int MAX_PARTSIZE = 64*1024; // Don't let anybody request more than this
diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
index 7e5cd962f..7b62ace84 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
@@ -141,7 +141,7 @@ public class SnarkManager implements Snark.CompleteListener {
if (!_config.containsKey(PROP_I2CP_PORT))
_config.setProperty(PROP_I2CP_PORT, "7654");
if (!_config.containsKey(PROP_I2CP_OPTS))
- _config.setProperty(PROP_I2CP_OPTS, "inbound.length=2 inbound.lengthVariance=0 outbound.length=2 outbound.lengthVariance=0");
+ _config.setProperty(PROP_I2CP_OPTS, "inbound.length=2 inbound.lengthVariance=0 outbound.length=2 outbound.lengthVariance=0 inbound.quantity=3 outbound.quantity=3");
if (!_config.containsKey(PROP_EEP_HOST))
_config.setProperty(PROP_EEP_HOST, "localhost");
if (!_config.containsKey(PROP_EEP_PORT))
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 c7ee93d7d..c791ad2fb 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
@@ -580,7 +580,7 @@ public class I2PSnarkServlet extends HttpServlet {
else if ("AUZV".equals(ch) || "AkZV".equals(ch) || "A0ZV".equals(ch))
client = "Robert";
else
- client = "Unknown";
+ client = "Unknown (" + ch + ')';
out.write("" + client + " " + peer.toString().substring(5, 9) + "");
if (showDebug)
out.write(" inactive " + (peer.getInactiveTime() / 1000) + "s");
diff --git a/apps/i2ptunnel/java/build.xml b/apps/i2ptunnel/java/build.xml
index 635cad2e4..564f6fc4b 100644
--- a/apps/i2ptunnel/java/build.xml
+++ b/apps/i2ptunnel/java/build.xml
@@ -42,7 +42,7 @@
+ basedir="../jsp/" excludes="web.xml, **/*.java, *.jsp">
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java
index d6e5bf9f9..38311eaf1 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java
@@ -27,6 +27,7 @@ import net.i2p.data.Destination;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runnable {
@@ -401,7 +402,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
if (_maxWaitTime > 0)
- SimpleTimer.getInstance().addEvent(new CloseEvent(s), _maxWaitTime);
+ SimpleScheduler.getInstance().addEvent(new CloseEvent(s), _maxWaitTime);
synchronized (_waitingSockets) {
_waitingSockets.add(s);
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java
index 252d4e1aa..38c50f266 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java
@@ -361,24 +361,24 @@ public class SOCKS5Server extends SOCKSServer {
/*
* Some namespaces to enclose SOCKS protocol codes
*/
- private class Method {
+ private static class Method {
private static final int NO_AUTH_REQUIRED = 0x00;
private static final int NO_ACCEPTABLE_METHODS = 0xff;
}
- private class AddressType {
+ private static class AddressType {
private static final int IPV4 = 0x01;
private static final int DOMAINNAME = 0x03;
private static final int IPV6 = 0x04;
}
- private class Command {
+ private static class Command {
private static final int CONNECT = 0x01;
private static final int BIND = 0x02;
private static final int UDP_ASSOCIATE = 0x03;
}
- private class Reply {
+ private static class Reply {
private static final int SUCCEEDED = 0x00;
private static final int GENERAL_SOCKS_SERVER_FAILURE = 0x01;
private static final int CONNECTION_NOT_ALLOWED_BY_RULESET = 0x02;
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigAdvancedHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigAdvancedHelper.java
index c90194860..3ab6354a6 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigAdvancedHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigAdvancedHelper.java
@@ -6,22 +6,7 @@ import java.util.TreeSet;
import net.i2p.router.RouterContext;
-public class ConfigAdvancedHelper {
- private RouterContext _context;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class ConfigAdvancedHelper extends HelperBase {
public ConfigAdvancedHelper() {}
public String getSettings() {
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java
index d6441736a..2bee43533 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java
@@ -9,22 +9,7 @@ import java.util.TreeSet;
import net.i2p.router.RouterContext;
import net.i2p.router.startup.ClientAppConfig;
-public class ConfigClientsHelper {
- private RouterContext _context;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class ConfigClientsHelper extends HelperBase {
public ConfigClientsHelper() {}
public String getForm1() {
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigKeyringHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigKeyringHelper.java
index 48bc15068..85c8ee423 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigKeyringHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigKeyringHelper.java
@@ -6,22 +6,7 @@ import java.io.OutputStreamWriter;
import net.i2p.router.RouterContext;
-public class ConfigKeyringHelper {
- private RouterContext _context;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class ConfigKeyringHelper extends HelperBase {
public ConfigKeyringHelper() {}
public String getSummary() {
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigLoggingHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigLoggingHelper.java
index 07acb0849..635d2e544 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigLoggingHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigLoggingHelper.java
@@ -6,22 +6,7 @@ import java.util.TreeSet;
import net.i2p.router.RouterContext;
-public class ConfigLoggingHelper {
- private RouterContext _context;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class ConfigLoggingHelper extends HelperBase {
public ConfigLoggingHelper() {}
public String getLogFilePattern() {
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 d355e9d61..9beeb33cf 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java
@@ -10,22 +10,7 @@ import net.i2p.router.transport.udp.UDPAddress;
import net.i2p.router.transport.udp.UDPTransport;
import net.i2p.time.Timestamper;
-public class ConfigNetHelper {
- private RouterContext _context;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class ConfigNetHelper extends HelperBase {
public ConfigNetHelper() {}
/** copied from various private components */
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigPeerHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigPeerHelper.java
index 63fc1f5e5..662a078b8 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigPeerHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigPeerHelper.java
@@ -4,25 +4,9 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
-import net.i2p.data.DataHelper;
import net.i2p.router.RouterContext;
-public class ConfigPeerHelper {
- private RouterContext _context;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class ConfigPeerHelper extends HelperBase {
public ConfigPeerHelper() {}
public String getBlocklistSummary() {
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigStatsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigStatsHelper.java
index 925fce79a..3af4ffafb 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigStatsHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigStatsHelper.java
@@ -15,8 +15,7 @@ import net.i2p.stat.RateStat;
import net.i2p.stat.StatManager;
import net.i2p.util.Log;
-public class ConfigStatsHelper {
- private RouterContext _context;
+public class ConfigStatsHelper extends HelperBase {
private Log _log;
private String _filter;
private Set _filters;
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigTunnelsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigTunnelsHelper.java
index 98141771b..e21f9d9ce 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigTunnelsHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigTunnelsHelper.java
@@ -8,22 +8,7 @@ import net.i2p.data.Destination;
import net.i2p.router.RouterContext;
import net.i2p.router.TunnelPoolSettings;
-public class ConfigTunnelsHelper {
- private RouterContext _context;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class ConfigTunnelsHelper extends HelperBase {
public ConfigTunnelsHelper() {}
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java
index 68e2ec5b9..818b748a7 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java
@@ -51,7 +51,7 @@ public class ConfigUpdateHandler extends FormHandler {
if ( (_updatePolicy == null) || (!_updatePolicy.equals("notify")) )
addFormNotice("Update available, attempting to download now");
else
- addFormNotice("Update available, click link on left to download");
+ addFormNotice("Update available, click button on left to download");
} else
addFormNotice("No update available");
}
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java
index 0ecaca4f0..d0d243799 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java
@@ -4,22 +4,7 @@ import net.i2p.crypto.TrustedUpdate;
import net.i2p.data.DataHelper;
import net.i2p.router.RouterContext;
-public class ConfigUpdateHelper {
- private RouterContext _context;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class ConfigUpdateHelper extends HelperBase {
public ConfigUpdateHelper() {}
public boolean updateAvailable() {
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ContentHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ContentHelper.java
index edacfaa41..ce29250b9 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ContentHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ContentHelper.java
@@ -6,25 +6,11 @@ import java.util.Locale;
import net.i2p.router.RouterContext;
import net.i2p.util.FileUtil;
-public class ContentHelper {
+public class ContentHelper extends HelperBase {
private String _page;
private int _maxLines;
private boolean _startAtBeginning;
private String _lang;
- private RouterContext _context;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
public ContentHelper() {}
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java
index 658caa1a3..16ce7337d 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java
@@ -11,27 +11,12 @@ import net.i2p.data.DataHelper;
import net.i2p.router.RouterContext;
import net.i2p.stat.Rate;
-public class GraphHelper {
- private RouterContext _context;
- private Writer _out;
+public class GraphHelper extends HelperBase {
private int _periodCount;
private boolean _showEvents;
private int _width;
private int _height;
private int _refreshDelaySeconds;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
public GraphHelper() {
_periodCount = 60; // SummaryListener.PERIODS;
@@ -41,7 +26,6 @@ public class GraphHelper {
_refreshDelaySeconds = 60;
}
- public void setOut(Writer out) { _out = out; }
public void setPeriodCount(String str) {
try { _periodCount = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
}
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/HelperBase.java b/apps/routerconsole/java/src/net/i2p/router/web/HelperBase.java
new file mode 100644
index 000000000..db5aa9ba2
--- /dev/null
+++ b/apps/routerconsole/java/src/net/i2p/router/web/HelperBase.java
@@ -0,0 +1,29 @@
+package net.i2p.router.web;
+
+import java.io.Writer;
+
+import net.i2p.router.RouterContext;
+
+/**
+ * Base helper
+ */
+public abstract class HelperBase {
+ protected RouterContext _context;
+ protected Writer _out;
+
+ /**
+ * Configure this bean to query a particular router context
+ *
+ * @param contextId begging few characters of the routerHash, or null to pick
+ * the first one we come across.
+ */
+ public void setContextId(String contextId) {
+ try {
+ _context = ContextHelper.getContext(contextId);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+ public void setWriter(Writer out) { _out = out; }
+}
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/JobQueueHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/JobQueueHelper.java
index a56cce19a..cf8ed2352 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/JobQueueHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/JobQueueHelper.java
@@ -7,27 +7,9 @@ import java.io.Writer;
import net.i2p.router.RouterContext;
-public class JobQueueHelper {
- private RouterContext _context;
- private Writer _out;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class JobQueueHelper extends HelperBase {
public JobQueueHelper() {}
- public void setWriter(Writer writer) { _out = writer; }
-
public String getJobQueueSummary() {
try {
if (_out != null) {
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java
index 67d2fc38c..e1fce8f3e 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/LogsHelper.java
@@ -5,22 +5,7 @@ import java.util.List;
import net.i2p.router.RouterContext;
import net.i2p.util.FileUtil;
-public class LogsHelper {
- private RouterContext _context;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class LogsHelper extends HelperBase {
public LogsHelper() {}
public String getLogs() {
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/NavHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/NavHelper.java
index a4b2125e3..2d50379f3 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/NavHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/NavHelper.java
@@ -6,22 +6,8 @@ import java.util.Map;
import net.i2p.router.RouterContext;
-public class NavHelper {
+public class NavHelper extends HelperBase {
private static Map _apps = new HashMap();
- private RouterContext _context;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
public NavHelper() {}
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 114579a27..a3280ac44 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/NetDbHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/NetDbHelper.java
@@ -7,29 +7,12 @@ import java.io.Writer;
import net.i2p.router.RouterContext;
-public class NetDbHelper {
- private RouterContext _context;
- private Writer _out;
+public class NetDbHelper extends HelperBase {
private String _routerPrefix;
private boolean _full = false;
-
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
public NetDbHelper() {}
- public void setWriter(Writer writer) { _out = writer; }
public void setRouter(String r) { _routerPrefix = r; }
public void setFull(String f) { _full = "1".equals(f); };
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/NoticeHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/NoticeHelper.java
index cd656e9e9..d5ce2b0d9 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/NoticeHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/NoticeHelper.java
@@ -7,22 +7,7 @@ import net.i2p.router.RouterContext;
* Simple helper to query the appropriate router for data necessary to render
* any emergency notices
*/
-public class NoticeHelper {
- private RouterContext _context;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class NoticeHelper extends HelperBase {
public String getSystemNotice() {
if (true) return ""; // moved to the left hand nav
if (_context.router().gracefulShutdownInProgress()) {
@@ -35,4 +20,4 @@ public class NoticeHelper {
return "";
}
}
-}
\ No newline at end of file
+}
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/OldConsoleHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/OldConsoleHelper.java
index 556367e27..6237183ab 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/OldConsoleHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/OldConsoleHelper.java
@@ -8,29 +8,9 @@ import java.io.Writer;
import net.i2p.router.RouterContext;
import net.i2p.router.admin.StatsGenerator;
-public class OldConsoleHelper {
- private RouterContext _context;
- private Writer _out;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class OldConsoleHelper extends HelperBase {
public OldConsoleHelper() {}
- public void setWriter(Writer writer) {
- _out = writer;
- }
-
public String getConsole() {
try {
if (_out != null) {
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/PeerHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/PeerHelper.java
index e5561fe1f..2504067ac 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/PeerHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/PeerHelper.java
@@ -5,28 +5,12 @@ import java.io.Writer;
import net.i2p.router.RouterContext;
-public class PeerHelper {
- private RouterContext _context;
- private Writer _out;
+public class PeerHelper extends HelperBase {
private int _sortFlags;
private String _urlBase;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
public PeerHelper() {}
- public void setOut(Writer out) { _out = out; }
public void setSort(String flags) {
if (flags != null) {
try {
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ProfilesHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ProfilesHelper.java
index 4db1010a5..702a63e50 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ProfilesHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ProfilesHelper.java
@@ -6,22 +6,7 @@ import java.io.OutputStreamWriter;
import net.i2p.router.RouterContext;
-public class ProfilesHelper {
- private RouterContext _context;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class ProfilesHelper extends HelperBase {
public ProfilesHelper() {}
public String getProfileSummary() {
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/StatHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/StatHelper.java
index 8b67d2622..ce6fefd5d 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/StatHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/StatHelper.java
@@ -11,12 +11,10 @@ import net.i2p.router.RouterContext;
* uuuugly. dump the peer profile data if given a peer.
*
*/
-public class StatHelper {
+public class StatHelper extends HelperBase {
private String _peer;
- private Writer _writer;
public void setPeer(String peer) { _peer = peer; }
- public void setWriter(Writer writer) { _writer = writer; }
public String getProfile() {
RouterContext ctx = (RouterContext)net.i2p.router.RouterContext.listContexts().get(0);
@@ -25,10 +23,10 @@ public class StatHelper {
Hash peer = (Hash)iter.next();
if (peer.toBase64().startsWith(_peer)) {
try {
- WriterOutputStream wos = new WriterOutputStream(_writer);
+ WriterOutputStream wos = new WriterOutputStream(_out);
ctx.profileOrganizer().exportProfile(peer, wos);
wos.flush();
- _writer.flush();
+ _out.flush();
return "";
} catch (Exception e) {
e.printStackTrace();
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 ad8e7135d..2e56e858b 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java
@@ -25,22 +25,7 @@ import net.i2p.stat.RateStat;
* Simple helper to query the appropriate router for data necessary to render
* the summary sections on the router console.
*/
-public class SummaryHelper {
- private RouterContext _context;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class SummaryHelper extends HelperBase {
/**
* Retrieve the shortened 4 character ident for the router located within
* the current JVM at the given context.
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/TunnelHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/TunnelHelper.java
index 4d4eba76b..3cd8a96e3 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/TunnelHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/TunnelHelper.java
@@ -7,27 +7,9 @@ import java.io.Writer;
import net.i2p.router.RouterContext;
-public class TunnelHelper {
- private RouterContext _context;
- private Writer _out;
- /**
- * Configure this bean to query a particular router context
- *
- * @param contextId begging few characters of the routerHash, or null to pick
- * the first one we come across.
- */
- public void setContextId(String contextId) {
- try {
- _context = ContextHelper.getContext(contextId);
- } catch (Throwable t) {
- t.printStackTrace();
- }
- }
-
+public class TunnelHelper extends HelperBase {
public TunnelHelper() {}
- public void setWriter(Writer writer) { _out = writer; }
-
public String getTunnelSummary() {
try {
if (_out != null) {
diff --git a/apps/routerconsole/jsp/graphs.jsp b/apps/routerconsole/jsp/graphs.jsp
index 422bf19d6..06807f397 100644
--- a/apps/routerconsole/jsp/graphs.jsp
+++ b/apps/routerconsole/jsp/graphs.jsp
@@ -14,7 +14,7 @@
" />
-
+
diff --git a/apps/routerconsole/jsp/peers.jsp b/apps/routerconsole/jsp/peers.jsp
index a537af634..d3b941a34 100644
--- a/apps/routerconsole/jsp/peers.jsp
+++ b/apps/routerconsole/jsp/peers.jsp
@@ -13,7 +13,7 @@
" />
-
+
" />
diff --git a/apps/routerconsole/jsp/summary.jsp b/apps/routerconsole/jsp/summary.jsp
index 687ccf15a..48f3b4fef 100644
--- a/apps/routerconsole/jsp/summary.jsp
+++ b/apps/routerconsole/jsp/summary.jsp
@@ -63,11 +63,9 @@
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();
- if (uri.indexOf('?') > 0)
- uri = uri + "&reseedNonce=" + nonce;
- else
- uri = uri + "?reseedNonce=" + nonce;
- out.print(" reseed
");
+ out.print("\n");
}
}
// If a new reseed ain't running, and the last reseed had errors, show error message
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/Connection.java b/apps/streaming/java/src/net/i2p/client/streaming/Connection.java
index 431540d46..e493124d0 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/Connection.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/Connection.java
@@ -12,6 +12,7 @@ import net.i2p.client.I2PSession;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.util.Log;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@@ -247,7 +248,7 @@ public class Connection {
void sendReset() {
if (_disconnectScheduledOn < 0) {
_disconnectScheduledOn = _context.clock().now();
- SimpleTimer.getInstance().addEvent(new DisconnectEvent(), DISCONNECT_TIMEOUT);
+ SimpleScheduler.getInstance().addEvent(new DisconnectEvent(), DISCONNECT_TIMEOUT);
}
long now = _context.clock().now();
if (_resetSentOn + 10*1000 > now) return; // don't send resets too fast
@@ -461,7 +462,7 @@ public class Connection {
void resetReceived() {
if (_disconnectScheduledOn < 0) {
_disconnectScheduledOn = _context.clock().now();
- SimpleTimer.getInstance().addEvent(new DisconnectEvent(), DISCONNECT_TIMEOUT);
+ SimpleScheduler.getInstance().addEvent(new DisconnectEvent(), DISCONNECT_TIMEOUT);
}
_resetReceived = true;
MessageOutputStream mos = _outputStream;
@@ -509,7 +510,7 @@ public class Connection {
if (removeFromConMgr) {
if (_disconnectScheduledOn < 0) {
_disconnectScheduledOn = _context.clock().now();
- SimpleTimer.getInstance().addEvent(new DisconnectEvent(), DISCONNECT_TIMEOUT);
+ SimpleScheduler.getInstance().addEvent(new DisconnectEvent(), DISCONNECT_TIMEOUT);
}
}
_connected = false;
@@ -708,7 +709,7 @@ public class Connection {
_closeSentOn = when;
if (_disconnectScheduledOn < 0) {
_disconnectScheduledOn = _context.clock().now();
- SimpleTimer.getInstance().addEvent(new DisconnectEvent(), DISCONNECT_TIMEOUT);
+ SimpleScheduler.getInstance().addEvent(new DisconnectEvent(), DISCONNECT_TIMEOUT);
}
}
public long getCloseReceivedOn() { return _closeReceivedOn; }
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 7d1d4827f..a123708e4 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionHandler.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionHandler.java
@@ -5,6 +5,7 @@ import java.util.List;
import net.i2p.I2PAppContext;
import net.i2p.util.Log;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@@ -54,7 +55,7 @@ class ConnectionHandler {
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("Receive new SYN: " + packet + ": timeout in " + _acceptTimeout);
- RetransmissionTimer.getInstance().addEvent(new TimeoutSyn(packet), _acceptTimeout);
+ SimpleScheduler.getInstance().addEvent(new TimeoutSyn(packet), _acceptTimeout);
synchronized (_synQueue) {
_synQueue.add(packet);
_synQueue.notifyAll();
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java
index 7c445f038..f7b245cb8 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionPacketHandler.java
@@ -7,6 +7,7 @@ import net.i2p.I2PException;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.util.Log;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@@ -168,7 +169,7 @@ public class ConnectionPacketHandler {
// take note of congestion
if (_log.shouldLog(Log.WARN))
_log.warn("congestion.. dup " + packet);
- RetransmissionTimer.getInstance().addEvent(new AckDup(con), con.getOptions().getSendAckDelay());
+ SimpleScheduler.getInstance().addEvent(new AckDup(con), con.getOptions().getSendAckDelay());
//con.setNextSendTime(_context.clock().now() + con.getOptions().getSendAckDelay());
//fastAck = true;
} else {
diff --git a/apps/susidns/src/build.xml b/apps/susidns/src/build.xml
index f31340954..d3f5f1662 100644
--- a/apps/susidns/src/build.xml
+++ b/apps/susidns/src/build.xml
@@ -63,12 +63,10 @@
-
-
diff --git a/apps/susimail/build.xml b/apps/susimail/build.xml
index 2bdc4f164..abf2a88cf 100644
--- a/apps/susimail/build.xml
+++ b/apps/susimail/build.xml
@@ -19,7 +19,7 @@
+ basedir="src/" excludes="WEB-INF/web.xml LICENSE src/**/*">
diff --git a/apps/systray/java/src/net/i2p/apps/systray/SysTray.java b/apps/systray/java/src/net/i2p/apps/systray/SysTray.java
index 380c5b172..4a635fd08 100644
--- a/apps/systray/java/src/net/i2p/apps/systray/SysTray.java
+++ b/apps/systray/java/src/net/i2p/apps/systray/SysTray.java
@@ -11,6 +11,7 @@ package net.i2p.apps.systray;
import java.awt.Frame;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
import snoozesoft.systray4j.SysTrayMenu;
import snoozesoft.systray4j.SysTrayMenuEvent;
@@ -60,14 +61,13 @@ public class SysTray implements SysTrayMenuListener {
private SysTray() {
_sysTrayMenuIcon.addSysTrayMenuListener(this);
createSysTrayMenu();
- SimpleTimer.getInstance().addEvent(new RefreshDisplayEvent(), REFRESH_DISPLAY_FREQUENCY);
+ SimpleScheduler.getInstance().addPeriodicEvent(new RefreshDisplayEvent(), REFRESH_DISPLAY_FREQUENCY);
}
private static final long REFRESH_DISPLAY_FREQUENCY = 30*1000;
private class RefreshDisplayEvent implements SimpleTimer.TimedEvent {
public void timeReached() {
refreshDisplay();
- SimpleTimer.getInstance().addEvent(RefreshDisplayEvent.this, REFRESH_DISPLAY_FREQUENCY);
}
}
diff --git a/core/java/src/net/i2p/client/I2PSessionImpl.java b/core/java/src/net/i2p/client/I2PSessionImpl.java
index a57957107..d4ff7360a 100644
--- a/core/java/src/net/i2p/client/I2PSessionImpl.java
+++ b/core/java/src/net/i2p/client/I2PSessionImpl.java
@@ -40,6 +40,7 @@ import net.i2p.data.i2cp.MessagePayloadMessage;
import net.i2p.data.i2cp.SessionId;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@@ -369,7 +370,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix() + "Notified availability for session " + _sessionId + ", message " + id);
}
- SimpleTimer.getInstance().addEvent(new VerifyUsage(mid), 30*1000);
+ SimpleScheduler.getInstance().addEvent(new VerifyUsage(mid), 30*1000);
}
private class VerifyUsage implements SimpleTimer.TimedEvent {
private Long _msgId;
diff --git a/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java b/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java
index 1b160f8dd..0d71677a9 100644
--- a/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java
+++ b/core/java/src/net/i2p/crypto/TransientSessionKeyManager.java
@@ -24,6 +24,7 @@ import net.i2p.data.PublicKey;
import net.i2p.data.SessionKey;
import net.i2p.data.SessionTag;
import net.i2p.util.Log;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@@ -70,7 +71,7 @@ class TransientSessionKeyManager extends SessionKeyManager {
_inboundTagSets = new HashMap(1024);
context.statManager().createRateStat("crypto.sessionTagsExpired", "How many tags/sessions are expired?", "Encryption", new long[] { 10*60*1000, 60*60*1000, 3*60*60*1000 });
context.statManager().createRateStat("crypto.sessionTagsRemaining", "How many tags/sessions are remaining after a cleanup?", "Encryption", new long[] { 10*60*1000, 60*60*1000, 3*60*60*1000 });
- SimpleTimer.getInstance().addEvent(new CleanupEvent(), 60*1000);
+ SimpleScheduler.getInstance().addPeriodicEvent(new CleanupEvent(), 60*1000);
}
private TransientSessionKeyManager() { this(null); }
@@ -80,7 +81,6 @@ class TransientSessionKeyManager extends SessionKeyManager {
int expired = aggressiveExpire();
long expireTime = _context.clock().now() - beforeExpire;
_context.statManager().addRateData("crypto.sessionTagsExpired", expired, expireTime);
- SimpleTimer.getInstance().addEvent(CleanupEvent.this, 60*1000);
}
}
diff --git a/core/java/src/net/i2p/data/DataHelper.java b/core/java/src/net/i2p/data/DataHelper.java
index 4a074f17c..53e32a347 100644
--- a/core/java/src/net/i2p/data/DataHelper.java
+++ b/core/java/src/net/i2p/data/DataHelper.java
@@ -344,8 +344,9 @@ public class DataHelper {
long rv = 0;
for (int i = 0; i < numBytes; i++) {
- long cur = rawStream.read() & 0xFF;
+ long cur = rawStream.read();
if (cur == -1) throw new DataFormatException("Not enough bytes for the field");
+ cur &= 0xFF;
// we loop until we find a nonzero byte (or we reach the end)
if (cur != 0) {
// ok, data found, now iterate through it to fill the rv
@@ -355,9 +356,10 @@ public class DataHelper {
cur = cur << shiftAmount;
rv += cur;
if (j + 1 < remaining) {
- cur = rawStream.read() & 0xFF;
+ cur = rawStream.read();
if (cur == -1)
throw new DataFormatException("Not enough bytes for the field");
+ cur &= 0xFF;
}
}
break;
diff --git a/core/java/src/net/i2p/data/i2cp/RequestLeaseSetMessage.java b/core/java/src/net/i2p/data/i2cp/RequestLeaseSetMessage.java
index 2cd630db6..b5fca013d 100644
--- a/core/java/src/net/i2p/data/i2cp/RequestLeaseSetMessage.java
+++ b/core/java/src/net/i2p/data/i2cp/RequestLeaseSetMessage.java
@@ -156,7 +156,7 @@ public class RequestLeaseSetMessage extends I2CPMessageImpl {
return buf.toString();
}
- private class TunnelEndpoint {
+ private static class TunnelEndpoint {
private Hash _router;
private TunnelId _tunnelId;
@@ -186,4 +186,4 @@ public class RequestLeaseSetMessage extends I2CPMessageImpl {
_tunnelId = tunnelId;
}
}
-}
\ No newline at end of file
+}
diff --git a/core/java/src/net/i2p/util/ByteCache.java b/core/java/src/net/i2p/util/ByteCache.java
index aadc721aa..4bd3da6ef 100644
--- a/core/java/src/net/i2p/util/ByteCache.java
+++ b/core/java/src/net/i2p/util/ByteCache.java
@@ -55,7 +55,7 @@ public final class ByteCache {
_maxCached = maxCachedEntries;
_entrySize = entrySize;
_lastOverflow = -1;
- SimpleTimer.getInstance().addEvent(new Cleanup(), CLEANUP_FREQUENCY);
+ SimpleScheduler.getInstance().addPeriodicEvent(new Cleanup(), CLEANUP_FREQUENCY);
_log = I2PAppContext.getGlobalContext().logManager().getLog(ByteCache.class);
}
@@ -120,7 +120,6 @@ public final class ByteCache {
_log.debug("Removing " + toRemove + " cached entries of size " + _entrySize);
}
}
- SimpleTimer.getInstance().addEvent(Cleanup.this, CLEANUP_FREQUENCY);
}
}
}
diff --git a/core/java/src/net/i2p/util/SimpleScheduler.java b/core/java/src/net/i2p/util/SimpleScheduler.java
new file mode 100644
index 000000000..91415102c
--- /dev/null
+++ b/core/java/src/net/i2p/util/SimpleScheduler.java
@@ -0,0 +1,164 @@
+package net.i2p.util;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ThreadFactory;
+
+import net.i2p.I2PAppContext;
+
+/**
+ * Simple event scheduler - toss an event on the queue and it gets fired at the
+ * appropriate time. The method that is fired however should NOT block (otherwise
+ * they b0rk the timer).
+ *
+ * This is like SimpleScheduler but addEvent() for an existing event adds a second
+ * job. Events cannot be cancelled or rescheduled.
+ *
+ * For events that cannot or will not be cancelled or rescheduled -
+ * for example, a call such as:
+ * SimpleTimer.getInstance().addEvent(new FooEvent(bar), timeoutMs);
+ * use SimpleScheduler instead to reduce lock contention in SimpleTimer...
+ *
+ * For periodic events, use addPeriodicEvent(). Unlike SimpleTimer,
+ * uncaught Exceptions will not prevent subsequent executions.
+ *
+ * @author zzz
+ */
+public class SimpleScheduler {
+ private static final SimpleScheduler _instance = new SimpleScheduler();
+ public static SimpleScheduler getInstance() { return _instance; }
+ private static final int THREADS = 4;
+ private I2PAppContext _context;
+ private Log _log;
+ private ScheduledThreadPoolExecutor _executor;
+ private String _name;
+ private int _count;
+
+ protected SimpleScheduler() { this("SimpleScheduler"); }
+ protected SimpleScheduler(String name) {
+ _context = I2PAppContext.getGlobalContext();
+ _log = _context.logManager().getLog(SimpleScheduler.class);
+ _name = name;
+ _count = 0;
+ _executor = new ScheduledThreadPoolExecutor(THREADS, new CustomThreadFactory());
+ }
+
+ /**
+ * Removes the SimpleScheduler.
+ */
+ public void stop() {
+ _executor.shutdownNow();
+ }
+
+ /**
+ * Queue up the given event to be fired no sooner than timeoutMs from now.
+ *
+ * @param event
+ * @param timeoutMs
+ */
+ public void addEvent(SimpleTimer.TimedEvent event, long timeoutMs) {
+ if (event == null)
+ throw new IllegalArgumentException("addEvent null");
+ RunnableEvent re = new RunnableEvent(event, timeoutMs);
+ re.schedule();
+ }
+
+ public void addPeriodicEvent(SimpleTimer.TimedEvent event, long timeoutMs) {
+ addPeriodicEvent(event, timeoutMs, timeoutMs);
+ }
+
+ /**
+ * Queue up the given event to be fired after initialDelay and every
+ * timeoutMs thereafter. The TimedEvent must not do its own rescheduling.
+ * As all Exceptions are caught in run(), these will not prevent
+ * subsequent executions (unlike SimpleTimer, where the TimedEvent does
+ * its own rescheduling)
+ *
+ * @param event
+ * @param initialDelay (ms)
+ * @param timeoutMs
+ */
+ public void addPeriodicEvent(SimpleTimer.TimedEvent event, long initialDelay, long timeoutMs) {
+ if (event == null)
+ throw new IllegalArgumentException("addEvent null");
+ RunnableEvent re = new PeriodicRunnableEvent(event, initialDelay, timeoutMs);
+ re.schedule();
+ }
+
+ private class CustomThreadFactory implements ThreadFactory {
+ public Thread newThread(Runnable r) {
+ Thread rv = Executors.defaultThreadFactory().newThread(r);
+ rv.setName(_name + ' ' + (++_count) + '/' + THREADS);
+ rv.setDaemon(true);
+ return rv;
+ }
+ }
+
+ /**
+ * Same as SimpleTimer.TimedEvent but use run() instead of timeReached(), and remembers the time
+ */
+ private class RunnableEvent implements Runnable {
+ protected SimpleTimer.TimedEvent _timedEvent;
+ protected long _scheduled;
+
+ public RunnableEvent(SimpleTimer.TimedEvent t, long timeoutMs) {
+ if (_log.shouldLog(Log.DEBUG))
+ _log.debug("Creating w/ delay " + timeoutMs + " : " + t);
+ _timedEvent = t;
+ _scheduled = timeoutMs + System.currentTimeMillis();
+ }
+ public void schedule() {
+ _executor.schedule(this, _scheduled - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
+ }
+ public void run() {
+ if (_log.shouldLog(Log.DEBUG))
+ _log.debug("Running: " + _timedEvent);
+ long before = System.currentTimeMillis();
+ if (_log.shouldLog(Log.WARN) && before < _scheduled - 100)
+ _log.warn(_name + " wtf, early execution " + (_scheduled - before) + ": " + _timedEvent);
+ else if (_log.shouldLog(Log.WARN) && before > _scheduled + 1000)
+ _log.warn(" wtf, late execution " + (before - _scheduled) + ": " + _timedEvent + debug());
+ try {
+ _timedEvent.timeReached();
+ } catch (Throwable t) {
+ _log.log(Log.CRIT, _name + " wtf, event borked: " + _timedEvent, t);
+ }
+ long time = System.currentTimeMillis() - before;
+ if (time > 1000 && _log.shouldLog(Log.WARN))
+ _log.warn(_name + " wtf, event execution took " + time + ": " + _timedEvent);
+ long completed = _executor.getCompletedTaskCount();
+ if (_log.shouldLog(Log.INFO) && completed % 250 == 0)
+ _log.info(debug());
+ }
+ }
+
+ /** Run every timeoutMs. TimedEvent must not do its own reschedule via addEvent() */
+ private class PeriodicRunnableEvent extends RunnableEvent {
+ private long _timeoutMs;
+ private long _initialDelay;
+ public PeriodicRunnableEvent(SimpleTimer.TimedEvent t, long initialDelay, long timeoutMs) {
+ super(t, timeoutMs);
+ _initialDelay = initialDelay;
+ _timeoutMs = timeoutMs;
+ _scheduled = initialDelay + System.currentTimeMillis();
+ }
+ public void schedule() {
+ _executor.scheduleWithFixedDelay(this, _initialDelay, _timeoutMs, TimeUnit.MILLISECONDS);
+ }
+ public void run() {
+ super.run();
+ _scheduled = _timeoutMs + System.currentTimeMillis();
+ }
+ }
+
+ private String debug() {
+ return
+ " Pool: " + _name +
+ " Active: " + _executor.getActiveCount() + '/' + _executor.getPoolSize() +
+ " Completed: " + _executor.getCompletedTaskCount() +
+ " Queued: " + _executor.getQueue().size();
+ }
+}
+
diff --git a/router/java/src/net/i2p/router/Blocklist.java b/router/java/src/net/i2p/router/Blocklist.java
index 5f686c192..1c50eaa65 100644
--- a/router/java/src/net/i2p/router/Blocklist.java
+++ b/router/java/src/net/i2p/router/Blocklist.java
@@ -256,7 +256,7 @@ public class Blocklist {
}
}
- private class Entry {
+ private static class Entry {
String comment;
byte ip1[];
byte ip2[];
diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java
index f7342413a..033678924 100644
--- a/router/java/src/net/i2p/router/Router.java
+++ b/router/java/src/net/i2p/router/Router.java
@@ -43,6 +43,7 @@ import net.i2p.stat.StatManager;
import net.i2p.util.FileUtil;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@@ -257,7 +258,7 @@ public class Router {
_context.inNetMessagePool().startup();
startupQueue();
//_context.jobQueue().addJob(new CoalesceStatsJob(_context));
- SimpleTimer.getInstance().addEvent(new CoalesceStatsEvent(_context), 0);
+ SimpleScheduler.getInstance().addPeriodicEvent(new CoalesceStatsEvent(_context), 20*1000);
_context.jobQueue().addJob(new UpdateRoutingKeyModifierJob(_context));
warmupCrypto();
_sessionKeyPersistenceHelper.startup();
@@ -346,7 +347,7 @@ public class Router {
if (blockingRebuild)
r.timeReached();
else
- SimpleTimer.getInstance().addEvent(r, 0);
+ SimpleScheduler.getInstance().addEvent(r, 0);
} catch (DataFormatException dfe) {
_log.log(Log.CRIT, "Internal error - unable to sign our own address?!", dfe);
}
@@ -1261,8 +1262,6 @@ class CoalesceStatsEvent implements SimpleTimer.TimedEvent {
getContext().statManager().addRateData("bw.sendBps", (long)KBps, 60*1000);
}
}
-
- SimpleTimer.getInstance().addEvent(this, 20*1000);
}
}
diff --git a/router/java/src/net/i2p/router/Shitlist.java b/router/java/src/net/i2p/router/Shitlist.java
index 7d86926cf..2005366c2 100644
--- a/router/java/src/net/i2p/router/Shitlist.java
+++ b/router/java/src/net/i2p/router/Shitlist.java
@@ -36,7 +36,7 @@ public class Shitlist {
private RouterContext _context;
private Map _entries;
- private class Entry {
+ private static class Entry {
/** when it should expire, per the i2p clock */
long expireOn;
/** why they were shitlisted */
diff --git a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java
index 133ad142c..189568ead 100644
--- a/router/java/src/net/i2p/router/client/ClientConnectionRunner.java
+++ b/router/java/src/net/i2p/router/client/ClientConnectionRunner.java
@@ -38,6 +38,7 @@ import net.i2p.router.RouterContext;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
import net.i2p.util.RandomSource;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@@ -419,7 +420,7 @@ public class ClientConnectionRunner {
// theirs is newer
} else {
// ours is newer, so wait a few secs and retry
- SimpleTimer.getInstance().addEvent(new Rerequest(set, expirationTime, onCreateJob, onFailedJob), 3*1000);
+ SimpleScheduler.getInstance().addEvent(new Rerequest(set, expirationTime, onCreateJob, onFailedJob), 3*1000);
}
// fire onCreated?
return; // already requesting
diff --git a/router/java/src/net/i2p/router/peermanager/PeerManager.java b/router/java/src/net/i2p/router/peermanager/PeerManager.java
index b2b16a00d..1c265ee67 100644
--- a/router/java/src/net/i2p/router/peermanager/PeerManager.java
+++ b/router/java/src/net/i2p/router/peermanager/PeerManager.java
@@ -24,6 +24,7 @@ import net.i2p.router.PeerSelectionCriteria;
import net.i2p.router.RouterContext;
import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
import net.i2p.util.Log;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@@ -50,7 +51,7 @@ class PeerManager {
_peersByCapability[i] = new ArrayList(64);
loadProfiles();
////_context.jobQueue().addJob(new EvaluateProfilesJob(_context));
- SimpleTimer.getInstance().addEvent(new Reorg(), 0);
+ SimpleScheduler.getInstance().addPeriodicEvent(new Reorg(), 0, 30*1000);
//_context.jobQueue().addJob(new PersistProfilesJob(_context, this));
}
@@ -60,8 +61,6 @@ class PeerManager {
_organizer.reorganize(true);
} catch (Throwable t) {
_log.log(Log.CRIT, "Error evaluating profiles", t);
- } finally {
- SimpleTimer.getInstance().addEvent(Reorg.this, 30*1000);
}
}
}
diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPSendFinisher.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPSendFinisher.java
new file mode 100644
index 000000000..8d19c6249
--- /dev/null
+++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPSendFinisher.java
@@ -0,0 +1,89 @@
+package net.i2p.router.transport.ntcp;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ThreadFactory;
+
+import net.i2p.I2PAppContext;
+import net.i2p.router.OutNetMessage;
+import net.i2p.util.Log;
+
+/**
+ * Previously, NTCP was using SimpleTimer with a delay of 0, which
+ * was a real abuse.
+ *
+ * Here we use the non-scheduled, lockless ThreadPoolExecutor with
+ * a fixed pool size and an unbounded queue.
+ *
+ * The old implementation was having problems with lock contention;
+ * this should work a lot better - and not clog up the SimpleTimer queue.
+ *
+ * @author zzz
+ */
+public class NTCPSendFinisher {
+ private static final int THREADS = 4;
+ private I2PAppContext _context;
+ private NTCPTransport _transport;
+ private Log _log;
+ private int _count;
+ private ThreadPoolExecutor _executor;
+
+ public NTCPSendFinisher(I2PAppContext context, NTCPTransport transport) {
+ _context = context;
+ _log = _context.logManager().getLog(NTCPSendFinisher.class);
+ _transport = transport;
+ }
+
+ public void start() {
+ _count = 0;
+ _executor = new CustomThreadPoolExecutor();
+ }
+
+ public void stop() {
+ _executor.shutdownNow();
+ }
+
+ public void add(OutNetMessage msg) {
+ _executor.execute(new RunnableEvent(msg));
+ }
+
+ // not really needed for now but in case we want to add some hooks like afterExecute()
+ private class CustomThreadPoolExecutor extends ThreadPoolExecutor {
+ public CustomThreadPoolExecutor() {
+ // use unbounded queue, so maximumPoolSize and keepAliveTime have no effect
+ super(THREADS, THREADS, 1000, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue(), new CustomThreadFactory());
+ }
+ }
+
+ private class CustomThreadFactory implements ThreadFactory {
+ public Thread newThread(Runnable r) {
+ Thread rv = Executors.defaultThreadFactory().newThread(r);
+ rv.setName("NTCPSendFinisher " + (++_count) + '/' + THREADS);
+ rv.setDaemon(true);
+ return rv;
+ }
+ }
+
+ /**
+ * Call afterSend() for the message
+ */
+ private class RunnableEvent implements Runnable {
+ private OutNetMessage _msg;
+
+ public RunnableEvent(OutNetMessage msg) {
+ _msg = msg;
+ }
+
+ public void run() {
+ try {
+ _transport.afterSend(_msg, true, false, _msg.getSendTime());
+ } catch (Throwable t) {
+ _log.log(Log.CRIT, " wtf, afterSend borked", t);
+ }
+ }
+ }
+}
+
diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
index 4b5573917..c23245bae 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
@@ -27,7 +27,6 @@ import net.i2p.router.transport.Transport;
import net.i2p.router.transport.TransportBid;
import net.i2p.router.transport.TransportImpl;
import net.i2p.util.Log;
-import net.i2p.util.SimpleTimer;
/**
*
@@ -50,7 +49,7 @@ public class NTCPTransport extends TransportImpl {
private List _establishing;
private List _sent;
- private SendFinisher _finisher;
+ private NTCPSendFinisher _finisher;
public NTCPTransport(RouterContext ctx) {
super(ctx);
@@ -124,7 +123,7 @@ public class NTCPTransport extends TransportImpl {
_conByIdent = new HashMap(64);
_sent = new ArrayList(4);
- _finisher = new SendFinisher();
+ _finisher = new NTCPSendFinisher(ctx, this);
_pumper = new EventPumper(ctx, this);
_reader = new Reader(ctx);
@@ -310,27 +309,8 @@ public class NTCPTransport extends TransportImpl {
return countActivePeers() < getMaxConnections() * 4 / 5;
}
+ /** queue up afterSend call, which can take some time w/ jobs, etc */
void sendComplete(OutNetMessage msg) { _finisher.add(msg); }
- /** async afterSend call, which can take some time w/ jobs, etc */
- private class SendFinisher implements SimpleTimer.TimedEvent {
- public void add(OutNetMessage msg) {
- synchronized (_sent) { _sent.add(msg); }
- SimpleTimer.getInstance().addEvent(SendFinisher.this, 0);
- }
- public void timeReached() {
- int pending = 0;
- OutNetMessage msg = null;
- synchronized (_sent) {
- pending = _sent.size()-1;
- if (pending >= 0)
- msg = (OutNetMessage)_sent.remove(0);
- }
- if (msg != null)
- afterSend(msg, true, false, msg.getSendTime());
- if (pending > 0)
- SimpleTimer.getInstance().addEvent(SendFinisher.this, 0);
- }
- }
private boolean isEstablished(RouterIdentity peer) {
return isEstablished(peer.calculateHash());
@@ -412,6 +392,7 @@ public class NTCPTransport extends TransportImpl {
public RouterAddress startListening() {
if (_log.shouldLog(Log.DEBUG)) _log.debug("Starting ntcp transport listening");
+ _finisher.start();
_pumper.startPumping();
_reader.startReading(NUM_CONCURRENT_READERS);
@@ -423,6 +404,7 @@ public class NTCPTransport extends TransportImpl {
public RouterAddress restartListening(RouterAddress addr) {
if (_log.shouldLog(Log.DEBUG)) _log.debug("Restarting ntcp transport listening");
+ _finisher.start();
_pumper.startPumping();
_reader.startReading(NUM_CONCURRENT_READERS);
@@ -551,6 +533,7 @@ public class NTCPTransport extends TransportImpl {
_pumper.stopPumping();
_writer.stopWriting();
_reader.stopReading();
+ _finisher.stop();
Map cons = null;
synchronized (_conLock) {
cons = new HashMap(_conByIdent);
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 6ab159408..896fe1ce4 100644
--- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
+++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
@@ -22,6 +22,7 @@ import net.i2p.router.Router;
import net.i2p.router.RouterContext;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@@ -184,7 +185,7 @@ public class EstablishmentManager {
msg.getTarget().getIdentity(),
new SessionKey(addr.getIntroKey()), addr);
_outboundStates.put(to, state);
- SimpleTimer.getInstance().addEvent(new Expire(to, state), 10*1000);
+ SimpleScheduler.getInstance().addEvent(new Expire(to, state), 10*1000);
}
}
if (state != null) {
@@ -394,7 +395,7 @@ public class EstablishmentManager {
msg.getTarget().getIdentity(),
new SessionKey(addr.getIntroKey()), addr);
_outboundStates.put(to, qstate);
- SimpleTimer.getInstance().addEvent(new Expire(to, qstate), 10*1000);
+ SimpleScheduler.getInstance().addEvent(new Expire(to, qstate), 10*1000);
for (int i = 0; i < queued.size(); i++) {
OutNetMessage m = (OutNetMessage)queued.get(i);
@@ -477,7 +478,7 @@ public class EstablishmentManager {
dsm.setMessageExpiration(_context.clock().now()+10*1000);
dsm.setMessageId(_context.random().nextLong(I2NPMessage.MAX_ID_VALUE));
_transport.send(dsm, peer);
- SimpleTimer.getInstance().addEvent(new PublishToNewInbound(peer), 0);
+ SimpleScheduler.getInstance().addEvent(new PublishToNewInbound(peer), 0);
}
private class PublishToNewInbound implements SimpleTimer.TimedEvent {
private PeerState _peer;
@@ -629,7 +630,7 @@ public class EstablishmentManager {
}
}
}
- SimpleTimer.getInstance().addEvent(new FailIntroduction(state, nonce), INTRO_ATTEMPT_TIMEOUT);
+ SimpleScheduler.getInstance().addEvent(new FailIntroduction(state, nonce), INTRO_ATTEMPT_TIMEOUT);
state.setIntroNonce(nonce);
_context.statManager().addRateData("udp.sendIntroRelayRequest", 1, 0);
UDPPacket requests[] = _builder.buildRelayRequest(_transport, state, _transport.getIntroKey());
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 7aa3c2fa1..35c5511be 100644
--- a/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java
+++ b/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java
@@ -15,6 +15,7 @@ import net.i2p.data.SessionKey;
import net.i2p.router.CommSystemFacade;
import net.i2p.router.RouterContext;
import net.i2p.util.Log;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@@ -79,7 +80,7 @@ class PeerTestManager {
sendTestToBob();
- SimpleTimer.getInstance().addEvent(new ContinueTest(), RESEND_TIMEOUT);
+ SimpleScheduler.getInstance().addEvent(new ContinueTest(), RESEND_TIMEOUT);
}
private class ContinueTest implements SimpleTimer.TimedEvent {
@@ -103,7 +104,7 @@ class PeerTestManager {
// second message from Charlie yet
sendTestToCharlie();
}
- SimpleTimer.getInstance().addEvent(ContinueTest.this, RESEND_TIMEOUT);
+ SimpleScheduler.getInstance().addEvent(ContinueTest.this, RESEND_TIMEOUT);
}
}
}
@@ -430,7 +431,7 @@ class PeerTestManager {
synchronized (_activeTests) {
_activeTests.put(new Long(nonce), state);
}
- SimpleTimer.getInstance().addEvent(new RemoveTest(nonce), MAX_CHARLIE_LIFETIME);
+ SimpleScheduler.getInstance().addEvent(new RemoveTest(nonce), MAX_CHARLIE_LIFETIME);
}
UDPPacket packet = _packetBuilder.buildPeerTestToBob(bobIP, from.getPort(), aliceIP, alicePort, aliceIntroKey, nonce, state.getBobCipherKey(), state.getBobMACKey());
@@ -511,7 +512,7 @@ class PeerTestManager {
synchronized (_activeTests) {
_activeTests.put(new Long(nonce), state);
}
- SimpleTimer.getInstance().addEvent(new RemoveTest(nonce), MAX_CHARLIE_LIFETIME);
+ SimpleScheduler.getInstance().addEvent(new RemoveTest(nonce), MAX_CHARLIE_LIFETIME);
}
UDPPacket packet = _packetBuilder.buildPeerTestToCharlie(aliceIP, from.getPort(), aliceIntroKey, nonce,
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 10876a0e7..3535484c9 100644
--- a/router/java/src/net/i2p/router/transport/udp/UDPReceiver.java
+++ b/router/java/src/net/i2p/router/transport/udp/UDPReceiver.java
@@ -9,6 +9,7 @@ import net.i2p.router.RouterContext;
import net.i2p.router.transport.FIFOBandwidthLimiter;
import net.i2p.util.I2PThread;
import net.i2p.util.Log;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@@ -115,7 +116,7 @@ public class UDPReceiver {
long delay = ARTIFICIAL_DELAY_BASE + _context.random().nextInt(ARTIFICIAL_DELAY);
if (_log.shouldLog(Log.INFO))
_log.info("Delay packet " + packet + " for " + delay);
- SimpleTimer.getInstance().addEvent(new ArtificiallyDelayedReceive(packet), delay);
+ SimpleScheduler.getInstance().addEvent(new ArtificiallyDelayedReceive(packet), delay);
return -1;
}
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 03714d7ef..e5185defa 100644
--- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
+++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
@@ -33,6 +33,7 @@ import net.i2p.router.transport.Transport;
import net.i2p.router.transport.TransportBid;
import net.i2p.router.transport.TransportImpl;
import net.i2p.util.Log;
+import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/**
@@ -631,7 +632,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
}
if (added) {
_context.statManager().addRateData("udp.dropPeerDroplist", droplistSize, 0);
- SimpleTimer.getInstance().addEvent(new RemoveDropList(remote), DROPLIST_PERIOD);
+ SimpleScheduler.getInstance().addEvent(new RemoveDropList(remote), DROPLIST_PERIOD);
}
}
markUnreachable(peerHash);
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 390fe888d..3a84f4810 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java
@@ -46,6 +46,7 @@ class BuildExecutor implements Runnable {
_context.statManager().createRateStat("tunnel.buildRequestTime", "How long it takes to build a tunnel request", "Tunnels", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("tunnel.buildRequestZeroHopTime", "How long it takes to build a zero hop tunnel", "Tunnels", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("tunnel.pendingRemaining", "How many inbound requests are pending after a pass (period is how long the pass takes)?", "Tunnels", new long[] { 60*1000, 10*60*1000 });
+ _context.statManager().createRateStat("tunnel.buildFailFirstHop", "How often we fail to build a OB tunnel because we can't contact the first hop", "Tunnels", new long[] { 60*1000, 10*60*1000 });
// Get stat manager, get recognized bandwidth tiers
StatManager statMgr = _context.statManager();
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 3c2a9dd20..f6b4d3478 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java
@@ -61,6 +61,7 @@ class BuildHandler {
_context.statManager().createRateStat("tunnel.decryptRequestTime", "How long it takes to decrypt a new tunnel build request", "Tunnels", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("tunnel.rejectTimeout", "How often we reject a tunnel because we can't find the next hop", "Tunnels", new long[] { 60*1000, 10*60*1000 });
+ _context.statManager().createRateStat("tunnel.rejectTimeout2", "How often we fail a tunnel because we can't contact the next hop", "Tunnels", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("tunnel.rejectOverloaded", "How long we had to wait before processing the request (when it was rejected)", "Tunnels", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("tunnel.acceptLoad", "Delay before processing the accepted request", "Tunnels", new long[] { 60*1000, 10*60*1000 });
@@ -413,7 +414,7 @@ class BuildHandler {
}
}
- private class TimeoutReq extends JobImpl {
+ private static class TimeoutReq extends JobImpl {
private BuildMessageState _state;
private BuildRequestRecord _req;
private Hash _nextPeer;
@@ -425,10 +426,12 @@ class BuildHandler {
}
public String getName() { return "Timeout looking for next peer for tunnel join"; }
public void runJob() {
- getContext().statManager().addRateData("tunnel.rejectTimeout", 1, 1);
- if (_log.shouldLog(Log.WARN))
- _log.warn("Request " + _state.msg.getUniqueId()
- + " could no be satisfied, as the next peer could not be found: " + _nextPeer.toBase64());
+ getContext().statManager().addRateData("tunnel.rejectTimeout", 1, 0);
+ // logging commented out so class can be static
+ //if (_log.shouldLog(Log.WARN))
+ // _log.warn("Request " + _state.msg.getUniqueId()
+ // + " could no be satisfied, as the next peer could not be found: " + _nextPeer.toBase64());
+
// ??? should we blame the peer here? getContext().profileManager().tunnelTimedOut(_nextPeer);
getContext().messageHistory().tunnelRejected(_state.fromHash, new TunnelId(_req.readReceiveTunnelId()), _nextPeer,
"rejected because we couldn't find " + _nextPeer.toBase64() + ": " +
@@ -516,8 +519,9 @@ class BuildHandler {
+ " from " + (state.fromHash != null ? state.fromHash.toBase64() :
state.from != null ? state.from.calculateHash().toBase64() : "tunnel"));
+ HopConfig cfg = null;
if (response == 0) {
- HopConfig cfg = new HopConfig();
+ cfg = new HopConfig();
cfg.setCreation(_context.clock().now());
cfg.setExpiration(_context.clock().now() + 10*60*1000);
cfg.setIVKey(req.readIVKey());
@@ -593,6 +597,8 @@ class BuildHandler {
msg.setExpiration(state.msg.getMessageExpiration());
msg.setPriority(300);
msg.setTarget(nextPeerInfo);
+ if (response == 0)
+ msg.setOnFailedSendJob(new TunnelBuildNextHopFailJob(_context, cfg));
_context.outNetMessagePool().add(msg);
} else {
// send it to the reply tunnel on the reply peer within a new TunnelBuildReplyMessage
@@ -619,6 +625,8 @@ class BuildHandler {
outMsg.setMessage(m);
outMsg.setPriority(300);
outMsg.setTarget(nextPeerInfo);
+ if (response == 0)
+ outMsg.setOnFailedSendJob(new TunnelBuildNextHopFailJob(_context, cfg));
_context.outNetMessagePool().add(outMsg);
}
}
@@ -762,7 +770,7 @@ class BuildHandler {
}
/** normal inbound requests from other people */
- private class BuildMessageState {
+ private static class BuildMessageState {
TunnelBuildMessage msg;
RouterIdentity from;
Hash fromHash;
@@ -775,7 +783,7 @@ class BuildHandler {
}
}
/** replies for outbound tunnels that we have created */
- private class BuildReplyMessageState {
+ private static class BuildReplyMessageState {
TunnelBuildReplyMessage msg;
long recvTime;
public BuildReplyMessageState(I2NPMessage m) {
@@ -784,7 +792,7 @@ class BuildHandler {
}
}
/** replies for inbound tunnels we have created */
- private class BuildEndMessageState {
+ private static class BuildEndMessageState {
TunnelBuildMessage msg;
PooledTunnelCreatorConfig cfg;
long recvTime;
@@ -796,15 +804,35 @@ class BuildHandler {
}
// noop
- private class TunnelBuildMessageHandlerJob extends JobImpl {
+ private static class TunnelBuildMessageHandlerJob extends JobImpl {
private TunnelBuildMessageHandlerJob(RouterContext ctx) { super(ctx); }
public void runJob() {}
public String getName() { return "Receive tunnel build message"; }
}
// noop
- private class TunnelBuildReplyMessageHandlerJob extends JobImpl {
+ private static class TunnelBuildReplyMessageHandlerJob extends JobImpl {
private TunnelBuildReplyMessageHandlerJob(RouterContext ctx) { super(ctx); }
public void runJob() {}
public String getName() { return "Receive tunnel build reply message"; }
}
+
+ /**
+ * Remove the participating tunnel if we can't contact the next hop
+ * Not strictly necessary, as the entry doesn't use that much space,
+ * but it affects capacity calculations
+ */
+ private static class TunnelBuildNextHopFailJob extends JobImpl {
+ HopConfig _cfg;
+ private TunnelBuildNextHopFailJob(RouterContext ctx, HopConfig cfg) {
+ super(ctx);
+ _cfg = cfg;
+ }
+ public String getName() { return "Timeout contacting next peer for tunnel join"; }
+ public void runJob() {
+ getContext().tunnelDispatcher().remove(_cfg);
+ getContext().statManager().addRateData("tunnel.rejectTimeout2", 1, 0);
+ // static, no _log
+ //_log.error("Cant contact next hop for " + _cfg);
+ }
+ }
}
diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java b/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java
index a4917772f..21325be85 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java
@@ -12,6 +12,7 @@ import net.i2p.data.RouterInfo;
import net.i2p.data.TunnelId;
import net.i2p.data.i2np.I2NPMessage;
import net.i2p.data.i2np.TunnelBuildMessage;
+import net.i2p.router.JobImpl;
import net.i2p.router.OutNetMessage;
import net.i2p.router.RouterContext;
import net.i2p.router.TunnelInfo;
@@ -136,6 +137,7 @@ class BuildRequestor {
return;
}
outMsg.setTarget(peer);
+ outMsg.setOnFailedSendJob(new TunnelBuildFirstHopFailJob(ctx, pool, cfg, exec));
ctx.outNetMessagePool().add(outMsg);
}
if (log.shouldLog(Log.DEBUG))
@@ -213,4 +215,33 @@ class BuildRequestor {
ctx.jobQueue().addJob(expireJob);
// can it get much easier?
}
+
+ /**
+ * Do two important things if we can't get the build msg to the
+ * first hop on an outbound tunnel -
+ * - Call buildComplete() so we can get started on the next build
+ * without waiting for the full expire time
+ * - Blame the first hop in the profile
+ * Most likely to happen on an exploratory tunnel, obviously.
+ * Can't do this for inbound tunnels since the msg goes out an expl. tunnel.
+ */
+ private static class TunnelBuildFirstHopFailJob extends JobImpl {
+ TunnelPool _pool;
+ PooledTunnelCreatorConfig _cfg;
+ BuildExecutor _exec;
+ private TunnelBuildFirstHopFailJob(RouterContext ctx, TunnelPool pool, PooledTunnelCreatorConfig cfg, BuildExecutor exec) {
+ super(ctx);
+ _cfg = cfg;
+ _exec = exec;
+ _pool = pool;
+ }
+ public String getName() { return "Timeout contacting first peer for OB tunnel"; }
+ public void runJob() {
+ _exec.buildComplete(_cfg, _pool);
+ getContext().profileManager().tunnelTimedOut(_cfg.getPeer(1));
+ getContext().statManager().addRateData("tunnel.buildFailFirstHop", 1, 0);
+ // static, no _log
+ //System.err.println("Cant contact first hop for " + _cfg);
+ }
+ }
}
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 43120d0b0..c6b1f5b9a 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java
@@ -376,7 +376,7 @@ public class TunnelPoolManager implements TunnelManagerFacade {
_context.jobQueue().addJob(new BootstrapPool(_context, _outboundExploratory));
}
- private class BootstrapPool extends JobImpl {
+ private static class BootstrapPool extends JobImpl {
private TunnelPool _pool;
public BootstrapPool(RouterContext ctx, TunnelPool pool) {
super(ctx);