diff --git a/core/java/src/net/i2p/client/ATalk.java b/apps/atalk/src/ATalk.java similarity index 100% rename from core/java/src/net/i2p/client/ATalk.java rename to apps/atalk/src/ATalk.java diff --git a/apps/i2psnark/i2psnark.config b/apps/i2psnark/i2psnark.config new file mode 100644 index 0000000000000000000000000000000000000000..7315d1b5f8f9da7d00741295c39e7a6b101a3520 --- /dev/null +++ b/apps/i2psnark/i2psnark.config @@ -0,0 +1 @@ +i2psnark.dir=i2psnark diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index 4b531f6064711c6dc71cb23a3864a1a0896e79dc..dc10c3b1af61d304b12e4b7614de31cdd6c1e80f 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -365,7 +365,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 = 128; + private static final int MAX_FILES_PER_TORRENT = 256; /** set of filenames that we are dealing with */ public Set listTorrentFiles() { synchronized (_snarks) { return new HashSet(_snarks.keySet()); } } 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 e276ccd88f25aa0f3e7533b4a863ed3bf0487376..c5bb93b2153f5ba8713b455088c944df5b203cf2 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -88,8 +88,7 @@ public class I2PSnarkServlet extends HttpServlet { out.write("<table border=\"0\" width=\"100%\">\n"); out.write("<tr><td><a href=\"" + req.getRequestURI() + peerString + "\" class=\"snarkRefresh\">Refresh</a>\n"); out.write("<td><a href=\"http://forum.i2p/viewforum.php?f=21\" class=\"snarkRefresh\">Forum</a>\n"); - out.write("<tr><td><a href=\"http://codevoid.i2p/forums/5\" class=\"snarkRefresh\">Wishlist</a>\n"); - int count = 1; + int count = 0; Map trackers = _manager.getTrackers(); for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) { Map.Entry entry = (Map.Entry)iter.next(); @@ -574,6 +573,10 @@ public class I2PSnarkServlet extends HttpServlet { client = "I2P-BT"; else if ("LUFa".equals(ch)) client = "Azureus"; + else if ("CwsL".equals(ch)) + client = "I2PSnarkXL"; + else if ("AUZV".equals(ch)) + client = "Robert"; else client = "Unknown"; out.write("<font size=-1>" + client + "</font> <tt>" + peer.toString().substring(5, 9) + "</tt>"); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java index 38d9b2074ef801a6f4306f3f852c701b0669175f..0ddcd58a9dfad23964665658e7cd3f9fc83d425b 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java @@ -3,6 +3,7 @@ package net.i2p.router.web; import net.i2p.data.RouterInfo; import net.i2p.router.LoadTestManager; import net.i2p.router.Router; +import net.i2p.router.transport.FIFOBandwidthRefiller; import net.i2p.router.transport.udp.UDPTransport; import net.i2p.router.web.ConfigServiceHandler.UpdateWrapperManagerAndRekeyTask; import net.i2p.time.Timestamper; @@ -110,26 +111,6 @@ public class ConfigNetHandler extends FormHandler { boolean restartRequired = false; if (!_ratesOnly) { - if ( (_hostname != null) && (_hostname.length() > 0) ) { - String oldHost = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_TCP_HOSTNAME); - if ( (oldHost == null) || (!oldHost.equalsIgnoreCase(_hostname)) ) { - _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_TCP_HOSTNAME, _hostname); - addFormNotice("Updating hostname from " + oldHost + " to " + _hostname); - restartRequired = true; - } - } - if ( (_tcpPort != null) && (_tcpPort.length() > 0) ) { - String oldPort = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_TCP_PORT); - if ( (oldPort == null) && (_tcpPort.equals("8887")) ) { - // still on default.. noop - } else if ( (oldPort == null) || (!oldPort.equalsIgnoreCase(_tcpPort)) ) { - // its not the default OR it has changed - _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_TCP_PORT, _tcpPort); - addFormNotice("Updating TCP port from " + oldPort + " to " + _tcpPort); - restartRequired = true; - } - } - // Normalize some things to make the following code a little easier... String oldNHost = _context.router().getConfigSetting(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME); if (oldNHost == null) oldNHost = ""; @@ -181,7 +162,7 @@ public class ConfigNetHandler extends FormHandler { // still on default.. noop } else if ( (oldPort == null) || (!oldPort.equalsIgnoreCase(_udpPort)) ) { // its not the default OR it has changed - _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_TCP_PORT, _udpPort); + _context.router().setConfigSetting(ConfigNetHelper.PROP_I2NP_UDP_PORT, _udpPort); addFormNotice("Updating UDP port from " + oldPort + " to " + _udpPort); restartRequired = true; } @@ -193,9 +174,9 @@ public class ConfigNetHandler extends FormHandler { if (!_ratesOnly) { if (_sharePct != null) { - String old = _context.router().getConfigSetting(ConfigNetHelper.PROP_SHARE_PERCENTAGE); + String old = _context.router().getConfigSetting(Router.PROP_BANDWIDTH_SHARE_PERCENTAGE); if ( (old == null) || (!old.equalsIgnoreCase(_sharePct)) ) { - _context.router().setConfigSetting(ConfigNetHelper.PROP_SHARE_PERCENTAGE, _sharePct); + _context.router().setConfigSetting(Router.PROP_BANDWIDTH_SHARE_PERCENTAGE, _sharePct); addFormNotice("Updating bandwidth share percentage"); } } @@ -263,23 +244,23 @@ public class ConfigNetHandler extends FormHandler { private void updateRates() { boolean updated = false; if ( (_inboundRate != null) && (_inboundRate.length() > 0) ) { - _context.router().setConfigSetting(ConfigNetHelper.PROP_INBOUND_KBPS, _inboundRate); + _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BANDWIDTH, _inboundRate); updated = true; } if ( (_outboundRate != null) && (_outboundRate.length() > 0) ) { - _context.router().setConfigSetting(ConfigNetHelper.PROP_OUTBOUND_KBPS, _outboundRate); + _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BANDWIDTH, _outboundRate); updated = true; } if ( (_inboundBurstRate != null) && (_inboundBurstRate.length() > 0) ) { - _context.router().setConfigSetting(ConfigNetHelper.PROP_INBOUND_BURST_KBPS, _inboundBurstRate); + _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BURST_BANDWIDTH, _inboundBurstRate); updated = true; } if ( (_outboundBurstRate != null) && (_outboundBurstRate.length() > 0) ) { - _context.router().setConfigSetting(ConfigNetHelper.PROP_OUTBOUND_BURST_KBPS, _outboundBurstRate); + _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BURST_BANDWIDTH, _outboundBurstRate); updated = true; } - String inBurstRate = _context.router().getConfigSetting(ConfigNetHelper.PROP_INBOUND_BURST_KBPS); + String inBurstRate = _context.router().getConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BURST_BANDWIDTH); if (_inboundBurst != null) { int rateKBps = 0; @@ -292,12 +273,12 @@ public class ConfigNetHandler extends FormHandler { } if ( (rateKBps > 0) && (burstSeconds > 0) ) { int kb = rateKBps * burstSeconds; - _context.router().setConfigSetting(ConfigNetHelper.PROP_INBOUND_BURST, "" + kb); + _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_INBOUND_BANDWIDTH_PEAK, "" + kb); updated = true; } } - String outBurstRate = _context.router().getConfigSetting(ConfigNetHelper.PROP_OUTBOUND_BURST_KBPS); + String outBurstRate = _context.router().getConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BURST_BANDWIDTH); if (_outboundBurst != null) { int rateKBps = 0; @@ -310,12 +291,13 @@ public class ConfigNetHandler extends FormHandler { } if ( (rateKBps > 0) && (burstSeconds > 0) ) { int kb = rateKBps * burstSeconds; - _context.router().setConfigSetting(ConfigNetHelper.PROP_OUTBOUND_BURST, "" + kb); + _context.router().setConfigSetting(FIFOBandwidthRefiller.PROP_OUTBOUND_BANDWIDTH_PEAK, "" + kb); updated = true; } } if (updated && !_ratesOnly) + _context.bandwidthLimiter().reinitialize(); addFormNotice("Updated bandwidth limits"); } } 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 0b6a7b65df010d7e193642575c87f30844395fe4..b648d960753bd6e52108f11896cb2e80535510c7 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java @@ -5,6 +5,7 @@ import net.i2p.router.CommSystemFacade; import net.i2p.router.LoadTestManager; import net.i2p.router.Router; import net.i2p.router.RouterContext; +import net.i2p.router.transport.TransportManager; import net.i2p.router.transport.udp.UDPAddress; import net.i2p.router.transport.udp.UDPTransport; import net.i2p.time.Timestamper; @@ -27,37 +28,23 @@ public class ConfigNetHelper { public ConfigNetHelper() {} - /** copied from various private TCP components */ - public final static String PROP_I2NP_TCP_HOSTNAME = "i2np.tcp.hostname"; - public final static String PROP_I2NP_TCP_PORT = "i2np.tcp.port"; + /** copied from various private components */ public final static String PROP_I2NP_UDP_PORT = "i2np.udp.port"; public final static String PROP_I2NP_INTERNAL_UDP_PORT = "i2np.udp.internalPort"; - - public String getHostname() { - return _context.getProperty(PROP_I2NP_TCP_HOSTNAME); - } - public String getTcpPort() { - int port = 8887; - String val = _context.getProperty(PROP_I2NP_TCP_PORT); - if (val != null) { - try { - port = Integer.parseInt(val); - } catch (NumberFormatException nfe) { - // ignore, use default from above - } - } - return "" + port; - } 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 String getNtcphostname() { + if (!TransportManager.enableNTCP(_context)) + return "\" disabled=\"true"; String hostname = _context.getProperty(PROP_I2NP_NTCP_HOSTNAME); if (hostname == null) return ""; return hostname; } public String getNtcpport() { + if (!TransportManager.enableNTCP(_context)) + return "\" disabled=\"true"; String port = _context.getProperty(PROP_I2NP_NTCP_PORT); if (port == null) return ""; return port; @@ -116,6 +103,8 @@ public class ConfigNetHelper { } public String getTcpAutoPortChecked() { + if (!TransportManager.enableNTCP(_context)) + return " disabled=\"true\" "; String enabled = _context.getProperty(PROP_I2NP_NTCP_AUTO_PORT, "false"); if ( (enabled != null) && ("true".equalsIgnoreCase(enabled)) ) return " checked "; @@ -124,6 +113,8 @@ public class ConfigNetHelper { } public String getTcpAutoIPChecked() { + if (!TransportManager.enableNTCP(_context)) + return " disabled=\"true\" "; String enabled = _context.getProperty(PROP_I2NP_NTCP_AUTO_IP, "false"); if ( (enabled != null) && ("true".equalsIgnoreCase(enabled)) ) return " checked "; @@ -150,80 +141,33 @@ public class ConfigNetHelper { } } - public static final String PROP_INBOUND_KBPS = "i2np.bandwidth.inboundKBytesPerSecond"; - public static final String PROP_OUTBOUND_KBPS = "i2np.bandwidth.outboundKBytesPerSecond"; - public static final String PROP_INBOUND_BURST_KBPS = "i2np.bandwidth.inboundBurstKBytesPerSecond"; - public static final String PROP_OUTBOUND_BURST_KBPS = "i2np.bandwidth.outboundBurstKBytesPerSecond"; - public static final String PROP_INBOUND_BURST = "i2np.bandwidth.inboundBurstKBytes"; - public static final String PROP_OUTBOUND_BURST = "i2np.bandwidth.outboundBurstKBytes"; - public static final String PROP_SHARE_PERCENTAGE = "router.sharePercentage"; - public static final int DEFAULT_SHARE_PERCENTAGE = 80; - public String getInboundRate() { - String rate = _context.getProperty(PROP_INBOUND_KBPS); - if (rate != null) - return rate; - else - return "32"; + return "" + _context.bandwidthLimiter().getInboundKBytesPerSecond(); } public String getOutboundRate() { - String rate = _context.getProperty(PROP_OUTBOUND_KBPS); - if (rate != null) - return rate; - else - return "16"; + return "" + _context.bandwidthLimiter().getOutboundKBytesPerSecond(); } public String getInboundBurstRate() { - String rate = _context.getProperty(PROP_INBOUND_BURST_KBPS); - if (rate != null) - return rate; - else - return "48"; + return "" + _context.bandwidthLimiter().getInboundBurstKBytesPerSecond(); } public String getOutboundBurstRate() { - String rate = _context.getProperty(PROP_OUTBOUND_BURST_KBPS); - if (rate != null) - return rate; - else - return "32"; + return "" + _context.bandwidthLimiter().getOutboundBurstKBytesPerSecond(); } public String getInboundBurstFactorBox() { - String rate = _context.getProperty(PROP_INBOUND_BURST_KBPS); - String burst = _context.getProperty(PROP_INBOUND_BURST); int numSeconds = 1; - if ( (burst != null) && (rate != null) ) { - int rateKBps = 0; - int burstKB = 0; - try { - rateKBps = Integer.parseInt(rate); - burstKB = Integer.parseInt(burst); - } catch (NumberFormatException nfe) { - // ignore - } - if ( (rateKBps > 0) && (burstKB > 0) ) { - numSeconds = burstKB / rateKBps; - } - } + int rateKBps = _context.bandwidthLimiter().getInboundBurstKBytesPerSecond(); + int burstKB = _context.bandwidthLimiter().getInboundBurstBytes() * 1024; + if ( (rateKBps > 0) && (burstKB > 0) ) + numSeconds = burstKB / rateKBps; return getBurstFactor(numSeconds, "inboundburstfactor"); } public String getOutboundBurstFactorBox() { - String rate = _context.getProperty(PROP_OUTBOUND_BURST_KBPS); - String burst = _context.getProperty(PROP_OUTBOUND_BURST); int numSeconds = 1; - if ( (burst != null) && (rate != null) ) { - int rateKBps = 0; - int burstKB = 0; - try { - rateKBps = Integer.parseInt(rate); - burstKB = Integer.parseInt(burst); - } catch (NumberFormatException nfe) { - // ignore - } - if ( (rateKBps > 0) && (burstKB > 0) ) { - numSeconds = burstKB / rateKBps; - } - } + int rateKBps = _context.bandwidthLimiter().getOutboundBurstKBytesPerSecond(); + int burstKB = _context.bandwidthLimiter().getOutboundBurstBytes() * 1024; + if ( (rateKBps > 0) && (burstKB > 0) ) + numSeconds = burstKB / rateKBps; return getBurstFactor(numSeconds, "outboundburstfactor"); } @@ -254,43 +198,36 @@ public class ConfigNetHelper { } public String getSharePercentageBox() { - String pctStr = _context.getProperty(PROP_SHARE_PERCENTAGE); - int pct = DEFAULT_SHARE_PERCENTAGE; - if (pctStr != null) - try { pct = Integer.parseInt(pctStr); } catch (NumberFormatException nfe) {} + int pct = (int) (100 * _context.router().getSharePercentage()); StringBuffer buf = new StringBuffer(256); buf.append("<select name=\"sharePercentage\">\n"); boolean found = false; - for (int i = 30; i <= 100; i += 10) { - buf.append("<option value=\"").append(i).append("\" "); - if (pct == i) { + for (int i = 30; i <= 110; i += 10) { + int val = i; + if (i == 110) { + if (found) + break; + else + val = pct; + } + buf.append("<option value=\"").append(val).append("\" "); + if (pct == val) { buf.append("selected=\"true\" "); found = true; - } else if ( (i == DEFAULT_SHARE_PERCENTAGE) && (!found) ) { - buf.append("selected=\"true\" "); } - buf.append(">Up to ").append(i).append("%</option>\n"); + buf.append(">Up to ").append(val).append("%</option>\n"); } buf.append("</select>\n"); return buf.toString(); } + public static final int DEFAULT_SHARE_KBPS = 12; public int getShareBandwidth() { - String irate = _context.getProperty(PROP_INBOUND_KBPS, "32"); - String orate = _context.getProperty(PROP_OUTBOUND_KBPS, "16"); - String pctStr = _context.getProperty(PROP_SHARE_PERCENTAGE, "" + DEFAULT_SHARE_PERCENTAGE); - if ( (irate != null) && (orate != null) && (pctStr != null)) { - try { - int irateKBps = Integer.parseInt(irate); - int orateKBps = Integer.parseInt(orate); - if (irateKBps < 0 || orateKBps < 0) - return 12; - int pct = Integer.parseInt(pctStr); - return (int) (((float) pct) * Math.min(irateKBps, orateKBps) / 100); - } catch (NumberFormatException nfe) { - // ignore - } - } - return 12; + int irateKBps = _context.bandwidthLimiter().getInboundKBytesPerSecond(); + int orateKBps = _context.bandwidthLimiter().getOutboundKBytesPerSecond(); + double pct = _context.router().getSharePercentage(); + if (irateKBps < 0 || orateKBps < 0) + return DEFAULT_SHARE_KBPS; + return (int) (pct * Math.min(irateKBps, orateKBps)); } } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigRestartBean.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigRestartBean.java index b8c1f3ca22d5b91f7d377cdd0ea53ddda145d24f..2b8817a31e1e4406e36a101f40d868896815b85d 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigRestartBean.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigRestartBean.java @@ -59,8 +59,12 @@ public class ConfigRestartBean { + "<a href=\"" + urlBase + "?consoleNonce=" + systemNonce + "&action=cancelShutdown\">Cancel restart</a> "; } } else { - return "<a href=\"" + urlBase + "?consoleNonce=" + systemNonce + "&action=restart\" title=\"Graceful restart\">Restart</a> " - + "<a href=\"" + urlBase + "?consoleNonce=" + systemNonce + "&action=shutdown\" title=\"Graceful shutdown\">Shutdown</a>"; + String shutdown = "<a href=\"" + urlBase + "?consoleNonce=" + systemNonce + "&action=shutdown\" title=\"Graceful shutdown\">Shutdown</a>"; + if (System.getProperty("wrapper.version") != null) + return "<a href=\"" + urlBase + "?consoleNonce=" + systemNonce + "&action=restart\" title=\"Graceful restart\">Restart</a> " + + shutdown; + else + return shutdown; } } 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 e0027e510e2ab3d086bde07acdece29aad2afd60..94b8eef61053b0c4cfbb5e92857bf3aaaca0964e 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java @@ -107,10 +107,12 @@ public class ConfigUpdateHelper { else buf.append("<option value=\"download\">Download and verify only</option>"); - if ("install".equals(policy)) - buf.append("<option value=\"install\" selected=\"true\">Download, verify, and restart</option>"); - else - buf.append("<option value=\"install\">Download, verify, and restart</option>"); + if (System.getProperty("wrapper.version") != null) { + if ("install".equals(policy)) + buf.append("<option value=\"install\" selected=\"true\">Download, verify, and restart</option>"); + else + buf.append("<option value=\"install\">Download, verify, and restart</option>"); + } buf.append("</select>\n"); return buf.toString(); 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 e728086be05e9dcfe4efaf72c8f98964cec45746..279650ebb758f47b72584d9856bf33473e38f9d7 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java @@ -143,6 +143,14 @@ public class SummaryHelper { return "ERR-UDP Port In Use - Set i2np.udp.internalPort=xxxx in advanced config and restart"; case CommSystemFacade.STATUS_UNKNOWN: // fallthrough default: + ra = _context.router().getRouterInfo().getTargetAddress("UDP"); + if (ra == null) { + if (_context.getProperty(ConfigNetHelper.PROP_I2NP_NTCP_HOSTNAME) == null || + _context.getProperty(ConfigNetHelper.PROP_I2NP_NTCP_PORT) == null) + return "ERR-UDP Disabled and Inbound TCP host/port not set"; + else + return "WARN-Firewalled with UDP Disabled"; + } return "Testing"; } } diff --git a/apps/routerconsole/jsp/config.jsp b/apps/routerconsole/jsp/config.jsp index 058229b2af0643b36da19ab267b566204e37d3b6..0d9573fe6c01a29774160ac96dd6daf2c6453f53 100644 --- a/apps/routerconsole/jsp/config.jsp +++ b/apps/routerconsole/jsp/config.jsp @@ -40,8 +40,7 @@ <input name="outboundburstrate" type="text" size="2" value="<jsp:getProperty name="nethelper" property="outboundBurstRate" />" /> KBps for <jsp:getProperty name="nethelper" property="outboundBurstFactorBox" /><br /> <i>KBps = kilobytes per second = 1024 bytes per second = 8192 bits per second.<br /> - A negative inbound rate means a default limit of 32KBytes per second. - A negative outbound rate means a default limit of 16KBytes per second.</i><br /> + A negative rate sets the default.</i><br /> Bandwidth share percentage: <jsp:getProperty name="nethelper" property="sharePercentageBox" /><br /> <% int share = nethelper.getShareBandwidth(); @@ -130,6 +129,11 @@ your UDP port is firewalled, and therefore it is likely that your TCP port is firewalled as well. If your TCP port is firewalled with inbound TCP enabled, routers will not be able to contact you via TCP, which will hurt the network. Please open your firewall or disable inbound TCP above. + <li><b>WARN - Firewalled with UDP Disabled</b> - + You have configured inbound TCP, however + you have disabled UDP. You appear to be firewalled on TCP, therefore your router cannot + accept inbound connections. + Please open your firewall or enable UDP. <li><b>ERR - Clock Skew</b> - Your system's clock is skewed, which will make it difficult to participate in the network. Correct your clock setting if this error persists. <li><b>ERR - Private TCP Address</b> - You must never advertise an unroutable IP address such as @@ -141,6 +145,10 @@ Check to see if another program is using port 8887. If so, stop that program or configure I2P to use a different port. This may be a transient error, if the other program is no longer using the port. However, a restart is always required after this error. + <li><b>ERR - UDP Disabled and Inbound TCP host/port not set</b> - + You have not configured inbound TCP with a hostname and port above, however + you have disabled UDP. Therefore your router cannot accept inbound connections. + Please configure a TCP host and port above or enable UDP. </ul> </p> <hr /> diff --git a/apps/routerconsole/jsp/summary.jsp b/apps/routerconsole/jsp/summary.jsp index 981f76df6bb1d69af05ce11e64e1e51b65b674eb..3080889141c43e37a588ee972e00d3e30617f39e 100644 --- a/apps/routerconsole/jsp/summary.jsp +++ b/apps/routerconsole/jsp/summary.jsp @@ -93,7 +93,6 @@ <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>PRNG wait/fill:</b> <jsp:getProperty name="helper" property="PRNGStatus" /><br /> <b><jsp:getProperty name="helper" property="tunnelStatus" /></b><br /> <hr /> diff --git a/apps/susidns/src/jsp/addressbook.jsp b/apps/susidns/src/jsp/addressbook.jsp index 1e78118b9e515bf0e51a32c730de3d5a90d0c60b..435ce2ec5618cc440e7b13e947eed0f583e035b3 100644 --- a/apps/susidns/src/jsp/addressbook.jsp +++ b/apps/susidns/src/jsp/addressbook.jsp @@ -136,7 +136,7 @@ <td class="names"><a href="http://${addr.name}/">${addr.name}</a> - <span class="addrhlpr"><a href="http://${addr.name}/?i2paddresshelper=${addr.destination}">(addrhlpr)</a></span> </td> -<td class="destinations"><input type="text" name="dest_${addr.name}" value="${addr.destination}" size="20"></td> +<td class="destinations"><textarea rows="1" cols="20" wrap="off" readonly="readonly" name="dest_${addr.name}" >${addr.destination}</textarea></td> </tr> </c:forEach> </table> @@ -160,7 +160,7 @@ <div id="add"> <p class="add"> <h3>Add new destination:</h3> -Hostname: <input type="text" name="hostname" value="" size="20"> Destination: <input type="text" name="destination" value="" size="20"><br/> +Hostname: <input type="text" name="hostname" value="" size="20"> Destination: <textarea rows="1" cols="20" wrap="off" ></textarea><br/> <input type="image" name="action" value="add" src="images/add.png" alt="Add destination" /> </p> </div> diff --git a/build.xml b/build.xml index f7e7030cb663d6be09df2f5263991aa669e44f07..cc19c5671f8a5e6a371c1d998c2a2e8397050113 100644 --- a/build.xml +++ b/build.xml @@ -229,6 +229,8 @@ <copy file="build/i2psnark.war" todir="pkg-temp/webapps/" /> <copy file="apps/i2psnark/java/build/launch-i2psnark.jar" todir="pkg-temp/" /> <copy file="apps/i2psnark/jetty-i2psnark.xml" todir="pkg-temp/" /> + <copy file="apps/i2psnark/i2psnark.config" todir="pkg-temp/" /> + <copy file="installer/resources/blocklist.txt" todir="pkg-temp/" /> <copy file="installer/resources/clients.config" todir="pkg-temp/" /> <copy file="installer/resources/eepget" todir="pkg-temp/" /> <copy file="installer/resources/i2prouter" todir="pkg-temp/" /> @@ -440,4 +442,40 @@ <ant dir="apps/i2psnark/java" target="standalone" /> <copy file="apps/i2psnark/java/i2psnark-standalone.zip" todir="." /> </target> + <target name="findbugs" depends="build2"> + <echo message="Starting findbugs, this will take a while..." /> + <exec executable="nice"> + <arg value="findbugs"/> + <arg value="-textui"/> + <arg value="-projectName"/> + <arg value="i2p"/> + <arg value="-sortByClass"/> + <arg value="-xml"/> + <arg value="-output"/> + <arg value="findbugs.xml"/> + <arg value="-auxclasspath"/> + <arg value="build/ant.jar:build/commons-el.jar:build/commons-logging.jar:build/jasper-compiler.jar:build/jasper-runtime.jar:build/javax.servlet.jar:build/org.mortbay.jetty.jar:apps/jrobin/jrobin-1.4.0.jar:apps/systray/java/lib/systray4j.jar:installer/lib/wrapper/linux/wrapper.jar:build/xercesImpl.jar"/> + <arg value="-sourcepath"/> + <arg value="apps/BOB/src/:apps/addressbook/java/src/:apps/i2psnark/java/src/:apps/i2ptunnel/java/src/:apps/ministreaming/java/src/:apps/routerconsole/java/src/:apps/sam/java/src/:apps/streaming/java/src/:apps/susidns/src/java/src/:apps/susimail/src/src/:apps/systray/java/src/:core/java/src/:router/java/src/"/> + <!-- start of the files to be analyzed --> + <arg value="build/BOB.jar"/> + <arg value="build/addressbook.war"/> + <arg value="build/i2p.jar"/> + <arg value="build/i2psnark.jar"/> + <arg value="build/i2psnark.war"/> + <arg value="build/i2ptunnel.jar"/> + <arg value="build/i2ptunnel.war"/> + <arg value="build/jbigi.jar"/> + <arg value="build/mstreaming.jar"/> + <arg value="build/router.jar/"/> + <!-- use the class files rather than the jar for routerconsole so we don't analyze jrobin --> + <arg value="apps/routerconsole/java/build/obj/"/> + <arg value="build/sam.jar"/> + <arg value="build/streaming.jar"/> + <arg value="build/susidns.war"/> + <arg value="build/susimail.war"/> + <arg value="build/systray.jar"/> + </exec> + <echo message="Findbugs output stored in findbugs.xml" /> + </target> </project> diff --git a/installer/i2pstandalone.xml b/installer/i2pstandalone.xml index 0044dd15ecbc47cd3c1ef14256e7741207434b48..9a6f0a65955b863e9ea49c637853bdd96a232b97 100644 --- a/installer/i2pstandalone.xml +++ b/installer/i2pstandalone.xml @@ -10,8 +10,8 @@ <minVersion>1.5.0</minVersion> <!-- <minHeapSize>64</minHeapSize> - <maxHeapSize>64</maxHeapSize> --> + <maxHeapSize>128</maxHeapSize> <args>-Djava.library.path=.;lib -DloggerFilenameOverride=logs/log-router-@.txt -Dorg.mortbay.http.Version.paranoid=true -Dorg.mortbay.util.FileResource.checkAliases=false</args> </jre> <splash> diff --git a/installer/resources/blocklist.txt b/installer/resources/blocklist.txt new file mode 100644 index 0000000000000000000000000000000000000000..8a1614e7f820c5bade45e75919366eae8e013aa7 --- /dev/null +++ b/installer/resources/blocklist.txt @@ -0,0 +1,35 @@ +# Blocking is now enabled by default. +# To disable blocking, set router.blocklist.enable=false on configadvanced.jsp and restart. +# +# Add additional entries as desired, sorting not required. +# This file is only read at router startup. +# To manually block a router after startup, use the form on http://localhost:7657/configpeer.jsp +# Warning - a large list will increase memory usage. +# Please do not block too broadly, it will segment and harm the network. +# For example, http://www.bluetack.co.uk/config/splist.zip is very broad and includes Tor users, it is not recommended. +# A more reasonable list: http://www.bluetack.co.uk/config/level1.zip +# +# You may also wish to add the bogons from http://www.cymru.com/Documents/bogon-list.html , +# but you will have top update your blocklist manually as IP ranges are assigned. +# You must update this list yourself, it is not overwritten by the update process. +# +# * Acceptable formats (IPV4 only): +# * #comment (# must be in column 1) +# * comment:IP-IP +# * comment:morecomments:IP-IP +# * (comments also allowed before any of the following) +# * IP-IP +# * IP/masklength +# * IP +# * hostname (DNS looked up at list readin time, not dynamically, so may not be much use) +# * 44-byte Base64 router hash +# * +# * No whitespace allowed after the last ':'. +# * +# * For further information and downloads: +# * http://www.bluetack.co.uk/forums/index.php?autocom=faq&CODE=02&qid=17 +# * http://blocklist.googlepages.com/ +# * http://www.cymru.com/Documents/bogon-list.html +# +Chinese Floodfill Flooder:159.226.40.7 +Friend of the Chinese Floodfill Flooder:159.226.40.3 diff --git a/installer/resources/jetty.xml b/installer/resources/jetty.xml index 038647d1cc04d6d32c49efed456aa7e04ebf6997..b55831e7440595b1e8c2479fc844232e0af33f96 100644 --- a/installer/resources/jetty.xml +++ b/installer/resources/jetty.xml @@ -58,7 +58,7 @@ <!-- Add a AJP13 listener on port 8009 --> <!-- This protocol can be used with mod_jk in apache, IIS etc. --> <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <!-- + <!-- UNCOMMENT TO ACTIVATE <Call name="addListener"> <Arg> <New class="org.mortbay.http.ajp.AJP13Listener"> @@ -87,12 +87,14 @@ <!-- + Upack the war file --> <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> <Set name="rootWebApp">root</Set> + <!-- UNCOMMENT TO ACTIVATE <Call name="addWebApplications"> <Arg></Arg> <Arg>./eepsite/webapps/</Arg> <Arg></Arg> <Arg type="boolean">true</Arg> </Call> + --> <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> diff --git a/installer/resources/wrapper.config b/installer/resources/wrapper.config index d546dbeff5c7403e5f959e032020df8063df4e37..2550f4e3dc428a27b77f33fc198fdf6ade953e73 100644 --- a/installer/resources/wrapper.config +++ b/installer/resources/wrapper.config @@ -6,6 +6,11 @@ # router console will NOT reread this file! You must # click "Shutdown", wait 11 minutes, then start i2p. # +# WARNING - The wrapper is NOT run (and this file is not used) +# if you start I2P with the 'no window' icon on Windows, or +# with the runplain.sh script on Linux. Use the 'restartable' +# icon on Windows or the i2prouter script on Linux to run the wrapper. +# #******************************************************************** # Java Application wrapper.java.command=java diff --git a/router/java/src/net/i2p/router/Blocklist.java b/router/java/src/net/i2p/router/Blocklist.java index 2d8da6c529f3b6b6653f5cf01711dc71b7e59ab3..5f686c19230f5f0b82bc837e80761b6f723c77f8 100644 --- a/router/java/src/net/i2p/router/Blocklist.java +++ b/router/java/src/net/i2p/router/Blocklist.java @@ -85,8 +85,7 @@ public class Blocklist { static final String BLOCKLIST_FILE_DEFAULT = "blocklist.txt"; public void startup() { - String enabled = _context.getProperty(PROP_BLOCKLIST_ENABLED, "false"); - if (! "true".equals(enabled)) + if (! Boolean.valueOf(_context.getProperty(PROP_BLOCKLIST_ENABLED, "true")).booleanValue()) return; String file = _context.getProperty(PROP_BLOCKLIST_FILE, BLOCKLIST_FILE_DEFAULT); // Maybe someday we'll read in multiple files and merge them @@ -173,8 +172,8 @@ public class Blocklist { private void readBlocklistFile(String file) { File BLFile = new File(file); if (BLFile == null || (!BLFile.exists()) || BLFile.length() <= 0) { - if (_log.shouldLog(Log.ERROR)) - _log.error("Blocklist file not found: " + file); + if (_log.shouldLog(Log.WARN)) + _log.warn("Blocklist file not found: " + file); return; } long start = _context.clock().now(); diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index 98fb1fccdef33c435f15a3979f822265c81467e9..40ecc31be43e738326689ad22277db1f790991d7 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -1072,11 +1072,13 @@ public class Router { return true; } - private static final String PROP_BANDWIDTH_SHARE_PERCENTAGE = "router.sharePercentage"; + public static final String PROP_BANDWIDTH_SHARE_PERCENTAGE = "router.sharePercentage"; + public static final int DEFAULT_SHARE_PERCENTAGE = 80; /** * What fraction of the bandwidth specified in our bandwidth limits should * we allow to be consumed by participating tunnels? + * @returns a number less than one, not a percentage! * */ public double getSharePercentage() { @@ -1095,7 +1097,7 @@ public class Router { _log.info("Unable to get the share percentage"); } } - return 0.8; + return DEFAULT_SHARE_PERCENTAGE / 100.0d; } public int get1sRate() { return get1sRate(false); } diff --git a/router/java/src/net/i2p/router/RouterThrottleImpl.java b/router/java/src/net/i2p/router/RouterThrottleImpl.java index 61d83f30e10dd4185ac435d44d27dbfda9694689..2c3f2114e58836880aff3f843c9c35162ea6875b 100644 --- a/router/java/src/net/i2p/router/RouterThrottleImpl.java +++ b/router/java/src/net/i2p/router/RouterThrottleImpl.java @@ -411,7 +411,10 @@ class RouterThrottleImpl implements RouterThrottle { } public long getMessageDelay() { - Rate delayRate = _context.statManager().getRate("transport.sendProcessingTime").getRate(60*1000); + RateStat rs = _context.statManager().getRate("transport.sendProcessingTime"); + if (rs == null) + return 0; + Rate delayRate = rs.getRate(60*1000); return (long)delayRate.getAverageValue(); } @@ -422,6 +425,8 @@ class RouterThrottleImpl implements RouterThrottle { public double getInboundRateDelta() { RateStat receiveRate = _context.statManager().getRate("transport.sendMessageSize"); + if (receiveRate == null) + return 0; double nowBps = getBps(receiveRate.getRate(60*1000)); double fiveMinBps = getBps(receiveRate.getRate(5*60*1000)); double hourBps = getBps(receiveRate.getRate(60*60*1000)); diff --git a/router/java/src/net/i2p/router/StatisticsManager.java b/router/java/src/net/i2p/router/StatisticsManager.java index 4b9f051439eb0924cd55cc0d10d910aecb9ad0ce..d959c25d3b01a5347c7b4f8695cfbb35b034ac35 100644 --- a/router/java/src/net/i2p/router/StatisticsManager.java +++ b/router/java/src/net/i2p/router/StatisticsManager.java @@ -91,8 +91,6 @@ public class StatisticsManager implements Service { } } - static final boolean CommentOutIn065 = RouterVersion.VERSION.equals("0.6.4"); - /** Retrieve a snapshot of the statistics that should be published */ public Properties publishStatistics() { Properties stats = new Properties(); @@ -186,8 +184,7 @@ public class StatisticsManager implements Service { //includeRate("udp.packetDequeueTime", stats, new long[] { 60*1000 }); //includeRate("udp.packetVerifyTime", stats, new long[] { 60*1000 }); - if(CommentOutIn065) - includeRate("tunnel.buildRequestTime", stats, new long[] { 10*60*1000 }); + //includeRate("tunnel.buildRequestTime", stats, new long[] { 10*60*1000 }); includeRate("tunnel.buildClientExpire", stats, new long[] { 10*60*1000 }); includeRate("tunnel.buildClientReject", stats, new long[] { 10*60*1000 }); includeRate("tunnel.buildClientSuccess", stats, new long[] { 10*60*1000 }); @@ -280,11 +277,13 @@ public class StatisticsManager implements Service { private void includeThroughput(Properties stats) { RateStat sendRate = _context.statManager().getRate("bw.sendRate"); if (sendRate != null) { - if (CommentOutIn065 && _context.router().getUptime() > 5*60*1000) { + /**** + if (_context.router().getUptime() > 5*60*1000) { Rate r = sendRate.getRate(5*60*1000); if (r != null) stats.setProperty("stat_bandwidthSendBps.5m", num(r.getAverageValue()) + ';' + num(r.getExtremeAverageValue()) + ";0;0;"); } + ****/ if (_context.router().getUptime() > 60*60*1000) { Rate r = sendRate.getRate(60*60*1000); if (r != null) @@ -294,11 +293,13 @@ public class StatisticsManager implements Service { RateStat recvRate = _context.statManager().getRate("bw.recvRate"); if (recvRate != null) { - if (CommentOutIn065 && _context.router().getUptime() > 5*60*1000) { + /**** + if (_context.router().getUptime() > 5*60*1000) { Rate r = recvRate.getRate(5*60*1000); if (r != null) stats.setProperty("stat_bandwidthReceiveBps.5m", num(r.getAverageValue()) + ';' + num(r.getExtremeAverageValue()) + ";0;0;"); } + ****/ if (_context.router().getUptime() > 60*60*1000) { Rate r = recvRate.getRate(60*60*1000); if (r != null) diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlyLookupMatchJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlyLookupMatchJob.java new file mode 100644 index 0000000000000000000000000000000000000000..0c77f80c53e1fd16b844bd16cc712f9d5f708a1e --- /dev/null +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlyLookupMatchJob.java @@ -0,0 +1,66 @@ +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.ReplyJob; +import net.i2p.router.RouterContext; +import net.i2p.util.Log; + +class FloodOnlyLookupMatchJob extends JobImpl implements ReplyJob { + private Log _log; + private FloodOnlySearchJob _search; + private DatabaseSearchReplyMessage _dsrm; + public FloodOnlyLookupMatchJob(RouterContext ctx, FloodOnlySearchJob job) { + super(ctx); + _log = ctx.logManager().getLog(getClass()); + _search = job; + _dsrm = null; + } + public void runJob() { + if ( (getContext().netDb().lookupLeaseSetLocally(_search.getKey()) != null) || + (getContext().netDb().lookupRouterInfoLocally(_search.getKey()) != null) ) { + if (_log.shouldLog(Log.INFO)) + _log.info(_search.getJobId() + ": search match and found locally"); + _search.success(); + } else { + int remaining = _search.getLookupsRemaining(); + if (_log.shouldLog(Log.INFO)) + _log.info(_search.getJobId() + ": got a DatabaseSearchReply when we were looking for " + + _search.getKey().toBase64() + ", with " + remaining + " outstanding searches"); + // netDb reply pointing us at other people + // Only process if we don't know enough floodfills + // This only works if both reply, otherwise we aren't called - should be fixed + if (_search.shouldProcessDSRM() && _dsrm != null) { + if (_log.shouldLog(Log.INFO)) + _log.info(_search.getJobId() + ": Processing DatabaseSearchReply"); + // Chase the hashes from the reply + getContext().jobQueue().addJob(new SingleLookupJob(getContext(), _dsrm)); + } + _search.failed(); + } + } + public String getName() { return "NetDb flood search (phase 1) match"; } + public void setMessage(I2NPMessage message) { + if (message instanceof DatabaseSearchReplyMessage) { + // a dsrm is only passed in when there are no more lookups remaining + // If more than one peer sent one, we only process the last one + // And sadly if the first peer sends a DRSM and the second one times out, + // this won't get called... + _dsrm = (DatabaseSearchReplyMessage) message; + _search.failed(); + return; + } + try { + DatabaseStoreMessage dsm = (DatabaseStoreMessage)message; + if (dsm.getValueType() == DatabaseStoreMessage.KEY_TYPE_LEASESET) + getContext().netDb().store(dsm.getKey(), dsm.getLeaseSet()); + else + getContext().netDb().store(dsm.getKey(), dsm.getRouterInfo()); + } catch (IllegalArgumentException iae) { + if (_log.shouldLog(Log.WARN)) + _log.warn(_search.getJobId() + ": Received an invalid store reply", iae); + } + } +} diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlyLookupSelector.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlyLookupSelector.java new file mode 100644 index 0000000000000000000000000000000000000000..b8c46fc33eecf366c8b523a438e1c697c6bdc5be --- /dev/null +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlyLookupSelector.java @@ -0,0 +1,51 @@ +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; + +class FloodOnlyLookupSelector implements MessageSelector { + private RouterContext _context; + private FloodOnlySearchJob _search; + private boolean _matchFound; + private Log _log; + public FloodOnlyLookupSelector(RouterContext ctx, FloodOnlySearchJob search) { + _context = ctx; + _search = search; + _log = ctx.logManager().getLog(getClass()); + _matchFound = false; + } + public boolean continueMatching() { + return _search.getLookupsRemaining() > 0 && !_matchFound && _context.clock().now() < getExpiration(); + } + public long getExpiration() { return (_matchFound ? -1 : _search.getExpiration()); } + public boolean isMatch(I2NPMessage message) { + if (message == null) return false; + if (message instanceof DatabaseStoreMessage) { + DatabaseStoreMessage dsm = (DatabaseStoreMessage)message; + // is it worth making sure the reply came in on the right tunnel? + if (_search.getKey().equals(dsm.getKey())) { + _search.decrementRemaining(); + _matchFound = true; + return true; + } + } else if (message instanceof DatabaseSearchReplyMessage) { + DatabaseSearchReplyMessage dsrm = (DatabaseSearchReplyMessage)message; + if (_search.getKey().equals(dsrm.getSearchKey())) { + _search.decrementRemaining(dsrm.getFromHash()); + // assume 0 old, all new, 0 invalid, 0 dup + _context.profileManager().dbLookupReply(dsrm.getFromHash(), 0, dsrm.getNumReplies(), 0, 0, + System.currentTimeMillis()-_search.getCreated()); + if (_search.getLookupsRemaining() <= 0) + return true; // ok, no more left, so time to fail + else + return false; + } + } + return false; + } +} diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlyLookupTimeoutJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlyLookupTimeoutJob.java new file mode 100644 index 0000000000000000000000000000000000000000..fc0bad90b7eb40a4b9824163feb7d86d5646a907 --- /dev/null +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlyLookupTimeoutJob.java @@ -0,0 +1,21 @@ +package net.i2p.router.networkdb.kademlia; + +import net.i2p.router.JobImpl; +import net.i2p.router.RouterContext; +import net.i2p.util.Log; + +class FloodOnlyLookupTimeoutJob extends JobImpl { + private FloodSearchJob _search; + private Log _log; + public FloodOnlyLookupTimeoutJob(RouterContext ctx, FloodOnlySearchJob job) { + super(ctx); + _search = job; + _log = ctx.logManager().getLog(getClass()); + } + public void runJob() { + if (_log.shouldLog(Log.INFO)) + _log.info(_search.getJobId() + ": search timed out"); + _search.failed(); + } + public String getName() { return "NetDb flood search (phase 1) timeout"; } +} 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 64708875bf087f77379975bb566118ea1a180877..5e68863026152c5ba58561df3759bfb06fc6c6ee 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java @@ -253,189 +253,3 @@ class FloodOnlySearchJob extends FloodSearchJob { } } } - -class FloodOnlyLookupTimeoutJob extends JobImpl { - private FloodSearchJob _search; - private Log _log; - public FloodOnlyLookupTimeoutJob(RouterContext ctx, FloodOnlySearchJob job) { - super(ctx); - _search = job; - _log = ctx.logManager().getLog(getClass()); - } - public void runJob() { - if (_log.shouldLog(Log.INFO)) - _log.info(_search.getJobId() + ": search timed out"); - _search.failed(); - } - public String getName() { return "NetDb flood search (phase 1) timeout"; } -} - -class FloodOnlyLookupMatchJob extends JobImpl implements ReplyJob { - private Log _log; - private FloodOnlySearchJob _search; - private DatabaseSearchReplyMessage _dsrm; - public FloodOnlyLookupMatchJob(RouterContext ctx, FloodOnlySearchJob job) { - super(ctx); - _log = ctx.logManager().getLog(getClass()); - _search = job; - _dsrm = null; - } - public void runJob() { - if ( (getContext().netDb().lookupLeaseSetLocally(_search.getKey()) != null) || - (getContext().netDb().lookupRouterInfoLocally(_search.getKey()) != null) ) { - if (_log.shouldLog(Log.INFO)) - _log.info(_search.getJobId() + ": search match and found locally"); - _search.success(); - } else { - int remaining = _search.getLookupsRemaining(); - if (_log.shouldLog(Log.INFO)) - _log.info(_search.getJobId() + ": got a DatabaseSearchReply when we were looking for " - + _search.getKey().toBase64() + ", with " + remaining + " outstanding searches"); - // netDb reply pointing us at other people - // Only process if we don't know enough floodfills - // This only works if both reply, otherwise we aren't called - should be fixed - if (_search.shouldProcessDSRM() && _dsrm != null) { - if (_log.shouldLog(Log.INFO)) - _log.info(_search.getJobId() + ": Processing DatabaseSearchReply"); - // Chase the hashes from the reply - getContext().jobQueue().addJob(new SingleLookupJob(getContext(), _dsrm)); - } - _search.failed(); - } - } - public String getName() { return "NetDb flood search (phase 1) match"; } - public void setMessage(I2NPMessage message) { - if (message instanceof DatabaseSearchReplyMessage) { - // a dsrm is only passed in when there are no more lookups remaining - // If more than one peer sent one, we only process the last one - // And sadly if the first peer sends a DRSM and the second one times out, - // this won't get called... - _dsrm = (DatabaseSearchReplyMessage) message; - _search.failed(); - return; - } - try { - DatabaseStoreMessage dsm = (DatabaseStoreMessage)message; - if (dsm.getValueType() == DatabaseStoreMessage.KEY_TYPE_LEASESET) - getContext().netDb().store(dsm.getKey(), dsm.getLeaseSet()); - else - getContext().netDb().store(dsm.getKey(), dsm.getRouterInfo()); - } catch (IllegalArgumentException iae) { - if (_log.shouldLog(Log.WARN)) - _log.warn(_search.getJobId() + ": Received an invalid store reply", iae); - } - } -} - -class FloodOnlyLookupSelector implements MessageSelector { - private RouterContext _context; - private FloodOnlySearchJob _search; - private boolean _matchFound; - private Log _log; - public FloodOnlyLookupSelector(RouterContext ctx, FloodOnlySearchJob search) { - _context = ctx; - _search = search; - _log = ctx.logManager().getLog(getClass()); - _matchFound = false; - } - public boolean continueMatching() { - return _search.getLookupsRemaining() > 0 && !_matchFound && _context.clock().now() < getExpiration(); - } - public long getExpiration() { return (_matchFound ? -1 : _search.getExpiration()); } - public boolean isMatch(I2NPMessage message) { - if (message == null) return false; - if (message instanceof DatabaseStoreMessage) { - DatabaseStoreMessage dsm = (DatabaseStoreMessage)message; - // is it worth making sure the reply came in on the right tunnel? - if (_search.getKey().equals(dsm.getKey())) { - _search.decrementRemaining(); - _matchFound = true; - return true; - } - } else if (message instanceof DatabaseSearchReplyMessage) { - DatabaseSearchReplyMessage dsrm = (DatabaseSearchReplyMessage)message; - if (_search.getKey().equals(dsrm.getSearchKey())) { - _search.decrementRemaining(dsrm.getFromHash()); - // assume 0 old, all new, 0 invalid, 0 dup - _context.profileManager().dbLookupReply(dsrm.getFromHash(), 0, dsrm.getNumReplies(), 0, 0, - System.currentTimeMillis()-_search.getCreated()); - if (_search.getLookupsRemaining() <= 0) - return true; // ok, no more left, so time to fail - else - return false; - } - } - return false; - } -} - -/** Below here, only used to lookup the DSRM reply hashes when we are short of floodfills **/ - -/** - * Ask the peer who sent us the DSRM for the RouterInfos. - * A simple version of SearchReplyJob in SearchJob.java. - * Skip the profile updates - this should be rare. - * - */ -class SingleLookupJob extends JobImpl { - private Log _log; - private DatabaseSearchReplyMessage _dsrm; - public SingleLookupJob(RouterContext ctx, DatabaseSearchReplyMessage dsrm) { - super(ctx); - _log = ctx.logManager().getLog(getClass()); - _dsrm = dsrm; - } - public void runJob() { - Hash from = _dsrm.getFromHash(); - for (int i = 0; i < _dsrm.getNumReplies(); i++) { - Hash peer = _dsrm.getReply(i); - if (peer.equals(getContext().routerHash())) // us - continue; - if (getContext().netDb().lookupRouterInfoLocally(peer) == null) - getContext().jobQueue().addJob(new SingleSearchJob(getContext(), peer, from)); - } - } - public String getName() { return "NetDb process DSRM"; } -} - -/** - * Ask a single peer for a single key. - * This isn't really a flood-only search job at all, but we extend - * FloodOnlySearchJob so we can use the same selectors, etc. - * - */ -class SingleSearchJob extends FloodOnlySearchJob { - Hash _to; - OutNetMessage _onm; - public SingleSearchJob(RouterContext ctx, Hash key, Hash to) { - // warning, null FloodfillNetworkDatabaseFacade ... - // define our own failed() and success() below so _facade isn't used. - super(ctx, null, key, null, null, 5*1000, false); - _to = to; - } - public String getName() { return "NetDb search key from DSRM"; } - public boolean shouldProcessDSRM() { return false; } // don't loop - public void runJob() { - _onm = getContext().messageRegistry().registerPending(_replySelector, _onReply, _onTimeout, _timeoutMs); - DatabaseLookupMessage dlm = new DatabaseLookupMessage(getContext(), true); - TunnelInfo replyTunnel = getContext().tunnelManager().selectInboundTunnel(); - TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundTunnel(); - if ( (replyTunnel == null) || (outTunnel == null) ) { - failed(); - return; - } - dlm.setFrom(replyTunnel.getPeer(0)); - dlm.setMessageExpiration(getContext().clock().now()+5*1000); - dlm.setReplyTunnel(replyTunnel.getReceiveTunnelId(0)); - dlm.setSearchKey(_key); - - if (_log.shouldLog(Log.INFO)) - _log.info(getJobId() + ": Single search for " + _key.toBase64() + " to " + _to.toBase64()); - getContext().tunnelDispatcher().dispatchOutbound(dlm, outTunnel.getSendTunnelId(0), _to); - _lookupsRemaining = 1; - } - void failed() { - getContext().messageRegistry().unregisterPending(_onm); - } - void success() {} -} 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 022f71695a7ffbad9a2ae7a35f174b75d588b968..77d2427cd79e41bde1bd28cfb524994cc3da1ba3 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/PersistentDataStore.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/PersistentDataStore.java @@ -231,6 +231,7 @@ class PersistentDataStore extends TransientDataStore { } } + /** This is only for manual reseeding? Why bother every 60 sec??? */ private class ReadJob extends JobImpl { private boolean _alreadyWarned; public ReadJob() { 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 34538dc9217d97c4f783506b6c7f07171fca904c..0f31fa9ec7fba601a1a76b7189b8f1423d5ff998 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/SearchJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/SearchJob.java @@ -775,146 +775,3 @@ class SearchJob extends JobImpl { boolean add(Hash peer) { return _facade.getKBuckets().add(peer); } void decrementOutstandingFloodfillSearches() { _floodfillSearchesOutstanding--; } } - -class SearchReplyJob extends JobImpl { - private DatabaseSearchReplyMessage _msg; - private Log _log; - /** - * Peer who we think sent us the reply. Note: could be spoofed! If the - * attacker knew we were searching for a particular key from a - * particular peer, they could send us some searchReply messages with - * shitty values, trying to get us to consider that peer unreliable. - * Potential fixes include either authenticated 'from' address or use a - * nonce in the search + searchReply (and check for it in the selector). - * - */ - private Hash _peer; - private int _curIndex; - private int _invalidPeers; - private int _seenPeers; - private int _newPeers; - private int _duplicatePeers; - private int _repliesPendingVerification; - private long _duration; - private SearchJob _searchJob; - public SearchReplyJob(RouterContext enclosingContext, SearchJob job, DatabaseSearchReplyMessage message, Hash peer, long duration) { - super(enclosingContext); - _log = enclosingContext.logManager().getLog(getClass()); - _searchJob = job; - _msg = message; - _peer = peer; - _curIndex = 0; - _invalidPeers = 0; - _seenPeers = 0; - _newPeers = 0; - _duplicatePeers = 0; - _repliesPendingVerification = 0; - if (duration > 0) - _duration = duration; - else - _duration = 0; - } - public String getName() { return "Process Reply for Kademlia Search"; } - public void runJob() { - if (_curIndex >= _msg.getNumReplies()) { - if (_repliesPendingVerification > 0) { - // we received new references from the peer, but still - // haven't verified all of them, so lets give it more time - requeue(_searchJob.timeoutMs()); - } else { - // either they didn't tell us anything new or we have verified - // (or failed to verify) all of them. we're done - getContext().profileManager().dbLookupReply(_peer, _newPeers, _seenPeers, - _invalidPeers, _duplicatePeers, _duration); - if (_newPeers > 0) - _searchJob.newPeersFound(_newPeers); - } - } else { - Hash peer = _msg.getReply(_curIndex); - - boolean shouldAdd = false; - - RouterInfo info = getContext().netDb().lookupRouterInfoLocally(peer); - if (info == null) { - // if the peer is giving us lots of bad peer references, - // dont try to fetch them. - - boolean sendsBadInfo = getContext().profileOrganizer().peerSendsBadReplies(_peer); - if (!sendsBadInfo) { - // we don't need to search for everthing we're given here - only ones that - // are next in our search path... - // note: no need to think about shitlisted targets in the netdb search, given - // the floodfill's behavior - // This keeps us from continually chasing blocklisted floodfills - if (getContext().shitlist().isShitlisted(peer)) { - // if (_log.shouldLog(Log.INFO)) - // _log.info("Not looking for a shitlisted peer..."); - // getContext().statManager().addRateData("netDb.searchReplyValidationSkipped", 1, 0); - } else { - //getContext().netDb().lookupRouterInfo(peer, new ReplyVerifiedJob(getContext(), peer), new ReplyNotVerifiedJob(getContext(), peer), _timeoutMs); - //_repliesPendingVerification++; - shouldAdd = true; - } - } else { - if (_log.shouldLog(Log.INFO)) - _log.info("Peer " + _peer.toBase64() + " sends us bad replies, so not verifying " + peer.toBase64()); - getContext().statManager().addRateData("netDb.searchReplyValidationSkipped", 1, 0); - } - } - - if (_searchJob.wasAttempted(peer)) { - _duplicatePeers++; - } - if (_log.shouldLog(Log.DEBUG)) - _log.debug(getJobId() + ": dbSearchReply received on search referencing router " + peer); - if (shouldAdd) { - if (_searchJob.add(peer)) - _newPeers++; - else - _seenPeers++; - } - - _curIndex++; - requeue(0); - } - } - void replyVerified() { - if (_log.shouldLog(Log.INFO)) - _log.info("Peer reply from " + _peer.toBase64()); - _repliesPendingVerification--; - getContext().statManager().addRateData("netDb.searchReplyValidated", 1, 0); - } - void replyNotVerified() { - if (_log.shouldLog(Log.INFO)) - _log.info("Peer reply from " + _peer.toBase64()); - _repliesPendingVerification--; - _invalidPeers++; - getContext().statManager().addRateData("netDb.searchReplyNotValidated", 1, 0); - } -} - -/** the peer gave us a reference to a new router, and we were able to fetch it */ -class ReplyVerifiedJob extends JobImpl { - private Hash _key; - private SearchReplyJob _replyJob; - public ReplyVerifiedJob(RouterContext enclosingContext, SearchReplyJob srj, Hash key) { - super(enclosingContext); - _replyJob = srj; - _key = key; - } - public String getName() { return "Search reply value verified"; } - public void runJob() { _replyJob.replyVerified(); } -} - -/** the peer gave us a reference to a new router, and we were NOT able to fetch it */ -class ReplyNotVerifiedJob extends JobImpl { - private Hash _key; - private SearchReplyJob _replyJob; - public ReplyNotVerifiedJob(RouterContext enclosingContext, SearchReplyJob srj, Hash key) { - super(enclosingContext); - _key = key; - _replyJob = srj; - } - public String getName() { return "Search reply value NOT verified"; } - public void runJob() { _replyJob.replyNotVerified(); } -} diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/SearchReplyJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/SearchReplyJob.java new file mode 100644 index 0000000000000000000000000000000000000000..892b5966ee80abc313ddf68e42d468cf655b689d --- /dev/null +++ b/router/java/src/net/i2p/router/networkdb/kademlia/SearchReplyJob.java @@ -0,0 +1,165 @@ +package net.i2p.router.networkdb.kademlia; + +import net.i2p.data.Hash; +import net.i2p.data.i2np.DatabaseSearchReplyMessage; +import net.i2p.data.RouterInfo; +import net.i2p.router.JobImpl; +import net.i2p.router.RouterContext; +import net.i2p.util.Log; + +/* + * free (adj.): unencumbered; not under the control of others + * Written by jrandom in 2003 and released into the public domain + * with no warranty of any kind, either expressed or implied. + * It probably won't make your computer catch on fire, or eat + * your children, but it might. Use at your own risk. + * + */ + +class SearchReplyJob extends JobImpl { + private DatabaseSearchReplyMessage _msg; + private Log _log; + /** + * Peer who we think sent us the reply. Note: could be spoofed! If the + * attacker knew we were searching for a particular key from a + * particular peer, they could send us some searchReply messages with + * shitty values, trying to get us to consider that peer unreliable. + * Potential fixes include either authenticated 'from' address or use a + * nonce in the search + searchReply (and check for it in the selector). + * + */ + private Hash _peer; + private int _curIndex; + private int _invalidPeers; + private int _seenPeers; + private int _newPeers; + private int _duplicatePeers; + private int _repliesPendingVerification; + private long _duration; + private SearchJob _searchJob; + public SearchReplyJob(RouterContext enclosingContext, SearchJob job, DatabaseSearchReplyMessage message, Hash peer, long duration) { + super(enclosingContext); + _log = enclosingContext.logManager().getLog(getClass()); + _searchJob = job; + _msg = message; + _peer = peer; + _curIndex = 0; + _invalidPeers = 0; + _seenPeers = 0; + _newPeers = 0; + _duplicatePeers = 0; + _repliesPendingVerification = 0; + if (duration > 0) + _duration = duration; + else + _duration = 0; + } + public String getName() { return "Process Reply for Kademlia Search"; } + public void runJob() { + if (_curIndex >= _msg.getNumReplies()) { + if (_repliesPendingVerification > 0) { + // we received new references from the peer, but still + // haven't verified all of them, so lets give it more time + requeue(_searchJob.timeoutMs()); + } else { + // either they didn't tell us anything new or we have verified + // (or failed to verify) all of them. we're done + getContext().profileManager().dbLookupReply(_peer, _newPeers, _seenPeers, + _invalidPeers, _duplicatePeers, _duration); + if (_newPeers > 0) + _searchJob.newPeersFound(_newPeers); + } + } else { + Hash peer = _msg.getReply(_curIndex); + + boolean shouldAdd = false; + + RouterInfo info = getContext().netDb().lookupRouterInfoLocally(peer); + if (info == null) { + // if the peer is giving us lots of bad peer references, + // dont try to fetch them. + + boolean sendsBadInfo = getContext().profileOrganizer().peerSendsBadReplies(_peer); + if (!sendsBadInfo) { + // we don't need to search for everthing we're given here - only ones that + // are next in our search path... + // note: no need to think about shitlisted targets in the netdb search, given + // the floodfill's behavior + // This keeps us from continually chasing blocklisted floodfills + if (getContext().shitlist().isShitlisted(peer)) { + // if (_log.shouldLog(Log.INFO)) + // _log.info("Not looking for a shitlisted peer..."); + // getContext().statManager().addRateData("netDb.searchReplyValidationSkipped", 1, 0); + } else { + //getContext().netDb().lookupRouterInfo(peer, new ReplyVerifiedJob(getContext(), peer), new ReplyNotVerifiedJob(getContext(), peer), _timeoutMs); + //_repliesPendingVerification++; + shouldAdd = true; + } + } else { + if (_log.shouldLog(Log.INFO)) + _log.info("Peer " + _peer.toBase64() + " sends us bad replies, so not verifying " + peer.toBase64()); + getContext().statManager().addRateData("netDb.searchReplyValidationSkipped", 1, 0); + } + } + + if (_searchJob.wasAttempted(peer)) { + _duplicatePeers++; + } + if (_log.shouldLog(Log.DEBUG)) + _log.debug(getJobId() + ": dbSearchReply received on search referencing router " + peer); + if (shouldAdd) { + if (_searchJob.add(peer)) + _newPeers++; + else + _seenPeers++; + } + + _curIndex++; + requeue(0); + } + } + void replyVerified() { + if (_log.shouldLog(Log.INFO)) + _log.info("Peer reply from " + _peer.toBase64()); + _repliesPendingVerification--; + getContext().statManager().addRateData("netDb.searchReplyValidated", 1, 0); + } + void replyNotVerified() { + if (_log.shouldLog(Log.INFO)) + _log.info("Peer reply from " + _peer.toBase64()); + _repliesPendingVerification--; + _invalidPeers++; + getContext().statManager().addRateData("netDb.searchReplyNotValidated", 1, 0); + } +} + +/** the peer gave us a reference to a new router, and we were able to fetch it */ +/*** +class ReplyVerifiedJob extends JobImpl { + private Hash _key; + private SearchReplyJob _replyJob; + public ReplyVerifiedJob(RouterContext enclosingContext, SearchReplyJob srj, Hash key) { + super(enclosingContext); + _replyJob = srj; + _key = key; + } + public String getName() { return "Search reply value verified"; } + public void runJob() { _replyJob.replyVerified(); } +} +***/ + +/** the peer gave us a reference to a new router, and we were NOT able to fetch it */ +/*** +class ReplyNotVerifiedJob extends JobImpl { + private Hash _key; + private SearchReplyJob _replyJob; + public ReplyNotVerifiedJob(RouterContext enclosingContext, SearchReplyJob srj, Hash key) { + super(enclosingContext); + _key = key; + _replyJob = srj; + } + public String getName() { return "Search reply value NOT verified"; } + public void runJob() { _replyJob.replyNotVerified(); } +} +***/ + diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/SingleLookupJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/SingleLookupJob.java new file mode 100644 index 0000000000000000000000000000000000000000..8c40d117b9842b434f6c1de677c1ec2aa6710f36 --- /dev/null +++ b/router/java/src/net/i2p/router/networkdb/kademlia/SingleLookupJob.java @@ -0,0 +1,34 @@ +package net.i2p.router.networkdb.kademlia; + +import net.i2p.data.Hash; +import net.i2p.data.i2np.DatabaseSearchReplyMessage; +import net.i2p.router.JobImpl; +import net.i2p.router.RouterContext; +import net.i2p.util.Log; + +/** + * Ask the peer who sent us the DSRM for the RouterInfos. + * A simple version of SearchReplyJob in SearchJob.java. + * Skip the profile updates - this should be rare. + * + */ +class SingleLookupJob extends JobImpl { + private Log _log; + private DatabaseSearchReplyMessage _dsrm; + public SingleLookupJob(RouterContext ctx, DatabaseSearchReplyMessage dsrm) { + super(ctx); + _log = ctx.logManager().getLog(getClass()); + _dsrm = dsrm; + } + public void runJob() { + Hash from = _dsrm.getFromHash(); + for (int i = 0; i < _dsrm.getNumReplies(); i++) { + Hash peer = _dsrm.getReply(i); + if (peer.equals(getContext().routerHash())) // us + continue; + if (getContext().netDb().lookupRouterInfoLocally(peer) == null) + getContext().jobQueue().addJob(new SingleSearchJob(getContext(), peer, from)); + } + } + public String getName() { return "NetDb process DSRM"; } +} diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/SingleSearchJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/SingleSearchJob.java new file mode 100644 index 0000000000000000000000000000000000000000..3ec005ec5ede2de0629d45ad2624468b83ae2435 --- /dev/null +++ b/router/java/src/net/i2p/router/networkdb/kademlia/SingleSearchJob.java @@ -0,0 +1,51 @@ +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; +import net.i2p.util.Log; + +/** + * Ask a single peer for a single key. + * This isn't really a flood-only search job at all, but we extend + * FloodOnlySearchJob so we can use the same selectors, etc. + * + */ +class SingleSearchJob extends FloodOnlySearchJob { + Hash _to; + OutNetMessage _onm; + public SingleSearchJob(RouterContext ctx, Hash key, Hash to) { + // warning, null FloodfillNetworkDatabaseFacade ... + // define our own failed() and success() below so _facade isn't used. + super(ctx, null, key, null, null, 5*1000, false); + _to = to; + } + public String getName() { return "NetDb search key from DSRM"; } + public boolean shouldProcessDSRM() { return false; } // don't loop + public void runJob() { + _onm = getContext().messageRegistry().registerPending(_replySelector, _onReply, _onTimeout, _timeoutMs); + DatabaseLookupMessage dlm = new DatabaseLookupMessage(getContext(), true); + TunnelInfo replyTunnel = getContext().tunnelManager().selectInboundTunnel(); + TunnelInfo outTunnel = getContext().tunnelManager().selectOutboundTunnel(); + if ( (replyTunnel == null) || (outTunnel == null) ) { + failed(); + return; + } + dlm.setFrom(replyTunnel.getPeer(0)); + dlm.setMessageExpiration(getContext().clock().now()+5*1000); + dlm.setReplyTunnel(replyTunnel.getReceiveTunnelId(0)); + dlm.setSearchKey(_key); + + if (_log.shouldLog(Log.INFO)) + _log.info(getJobId() + ": Single search for " + _key.toBase64() + " to " + _to.toBase64()); + getContext().tunnelDispatcher().dispatchOutbound(dlm, outTunnel.getSendTunnelId(0), _to); + _lookupsRemaining = 1; + } + void failed() { + getContext().messageRegistry().unregisterPending(_onm); + } + void success() {} +} diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/StartExplorersJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/StartExplorersJob.java index 7137ae57648f8f1f129fd115d4ceee0f8d3c0166..159cb8be6748a4a3d025caff6855e684d207c77e 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/StartExplorersJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/StartExplorersJob.java @@ -42,7 +42,8 @@ class StartExplorersJob extends JobImpl { public String getName() { return "Start Explorers Job"; } public void runJob() { Set toExplore = selectKeysToExplore(); - _log.debug("Keys to explore during this run: " + toExplore); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Keys to explore during this run: " + toExplore); _facade.removeFromExploreKeys(toExplore); for (Iterator iter = toExplore.iterator(); iter.hasNext(); ) { Hash key = (Hash)iter.next(); @@ -83,6 +84,8 @@ class StartExplorersJob extends JobImpl { */ private Set selectKeysToExplore() { Set queued = _facade.getExploreKeys(); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Keys waiting for exploration: " + queued.size()); if (queued.size() <= MAX_PER_RUN) return queued; Set rv = new HashSet(MAX_PER_RUN); diff --git a/router/java/src/net/i2p/router/peermanager/PeerManagerFacadeImpl.java b/router/java/src/net/i2p/router/peermanager/PeerManagerFacadeImpl.java index 305d4d9f4ad1d6537b5da5d4f857ca249ac97e00..3483873a5ab3d7e3e37a37ec75682725a93af320 100644 --- a/router/java/src/net/i2p/router/peermanager/PeerManagerFacadeImpl.java +++ b/router/java/src/net/i2p/router/peermanager/PeerManagerFacadeImpl.java @@ -47,7 +47,8 @@ public class PeerManagerFacadeImpl implements PeerManagerFacade { public void shutdown() { _log.info("Shutting down the peer manager"); _testJob.stopTesting(); - _manager.storeProfiles(); + if (_manager != null) + _manager.storeProfiles(); } public void restart() { diff --git a/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java b/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java index 0a51e754d0838ae353aab5a5dde246aa0e9a7780..86ba394e4b27f7436fd81f4dca39bb3d75384795 100644 --- a/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java +++ b/router/java/src/net/i2p/router/transport/FIFOBandwidthLimiter.java @@ -107,8 +107,11 @@ public class FIFOBandwidthLimiter { public float getSendBps15s() { return _sendBps15s; } public float getReceiveBps15s() { return _recvBps15s; } + /** These are the configured maximums, not the current rate */ public int getOutboundKBytesPerSecond() { return _refiller.getOutboundKBytesPerSecond(); } public int getInboundKBytesPerSecond() { return _refiller.getInboundKBytesPerSecond(); } + public int getOutboundBurstKBytesPerSecond() { return _refiller.getOutboundBurstKBytesPerSecond(); } + public int getInboundBurstKBytesPerSecond() { return _refiller.getInboundBurstKBytesPerSecond(); } public void reinitialize() { _pendingInboundRequests.clear(); @@ -191,8 +194,8 @@ public class FIFOBandwidthLimiter { void setOutboundBurstKBps(int kbytesPerSecond) { _maxOutbound = kbytesPerSecond * 1024; } - int getInboundBurstBytes() { return _maxInboundBurst; } - int getOutboundBurstBytes() { return _maxOutboundBurst; } + public int getInboundBurstBytes() { return _maxInboundBurst; } + public int getOutboundBurstBytes() { return _maxOutboundBurst; } void setInboundBurstBytes(int bytes) { _maxInboundBurst = bytes; } void setOutboundBurstBytes(int bytes) { _maxOutboundBurst = bytes; } diff --git a/router/java/src/net/i2p/router/transport/FIFOBandwidthRefiller.java b/router/java/src/net/i2p/router/transport/FIFOBandwidthRefiller.java index 6a116126ebd60f4113891c24de1bfacb298ad181..0210f8da5266113cae7a0bbb483fb37069d7b2ac 100644 --- a/router/java/src/net/i2p/router/transport/FIFOBandwidthRefiller.java +++ b/router/java/src/net/i2p/router/transport/FIFOBandwidthRefiller.java @@ -6,7 +6,7 @@ import java.util.List; import net.i2p.I2PAppContext; import net.i2p.util.Log; -class FIFOBandwidthRefiller implements Runnable { +public class FIFOBandwidthRefiller implements Runnable { private Log _log; private I2PAppContext _context; private FIFOBandwidthLimiter _limiter; @@ -34,9 +34,9 @@ class FIFOBandwidthRefiller implements Runnable { //public static final String PROP_REPLENISH_FREQUENCY = "i2np.bandwidth.replenishFrequencyMs"; // no longer allow unlimited bandwidth - the user must specify a value, and if they do not, it is 32/16KBps - public static final int DEFAULT_INBOUND_BANDWIDTH = 32; - public static final int DEFAULT_OUTBOUND_BANDWIDTH = 16; - public static final int DEFAULT_INBOUND_BURST_BANDWIDTH = 48; + public static final int DEFAULT_INBOUND_BANDWIDTH = 48; + public static final int DEFAULT_OUTBOUND_BANDWIDTH = 24; + public static final int DEFAULT_INBOUND_BURST_BANDWIDTH = 64; public static final int DEFAULT_OUTBOUND_BURST_BANDWIDTH = 32; public static final int DEFAULT_BURST_SECONDS = 60; @@ -217,10 +217,10 @@ class FIFOBandwidthRefiller implements Runnable { // bandwidth was specified *and* changed try { int in = Integer.parseInt(inBwStr); - if ( (in <= 0) || (in > MIN_INBOUND_BANDWIDTH) ) + if ( (in <= 0) || (in >= _inboundKBytesPerSecond) ) _inboundBurstKBytesPerSecond = in; else - _inboundBurstKBytesPerSecond = MIN_INBOUND_BANDWIDTH; + _inboundBurstKBytesPerSecond = _inboundKBytesPerSecond; if (_log.shouldLog(Log.DEBUG)) _log.debug("Updating inbound burst rate to " + _inboundBurstKBytesPerSecond); } catch (NumberFormatException nfe) { @@ -247,10 +247,10 @@ class FIFOBandwidthRefiller implements Runnable { // bandwidth was specified *and* changed try { int out = Integer.parseInt(outBwStr); - if ( (out <= 0) || (out >= MIN_OUTBOUND_BANDWIDTH) ) + if ( (out <= 0) || (out >= _outboundKBytesPerSecond) ) _outboundBurstKBytesPerSecond = out; else - _outboundBurstKBytesPerSecond = MIN_OUTBOUND_BANDWIDTH; + _outboundBurstKBytesPerSecond = _outboundKBytesPerSecond; if (_log.shouldLog(Log.DEBUG)) _log.debug("Updating outbound burst rate to " + _outboundBurstKBytesPerSecond); } catch (NumberFormatException nfe) { @@ -335,4 +335,6 @@ class FIFOBandwidthRefiller implements Runnable { int getOutboundKBytesPerSecond() { return _outboundKBytesPerSecond; } int getInboundKBytesPerSecond() { return _inboundKBytesPerSecond; } + int getOutboundBurstKBytesPerSecond() { return _outboundBurstKBytesPerSecond; } + int getInboundBurstKBytesPerSecond() { return _inboundBurstKBytesPerSecond; } } diff --git a/router/java/src/net/i2p/router/transport/TransportManager.java b/router/java/src/net/i2p/router/transport/TransportManager.java index 5979961bb9ac430f3eaaa9113c8e4291134c9ef6..3d49780c3eeb6456f82391e5f7efa5c141142b32 100644 --- a/router/java/src/net/i2p/router/transport/TransportManager.java +++ b/router/java/src/net/i2p/router/transport/TransportManager.java @@ -36,7 +36,6 @@ public class TransportManager implements TransportEventListener { private List _transports; private RouterContext _context; - private final static String PROP_DISABLE_TCP = "i2np.tcp.disable"; private final static String PROP_ENABLE_UDP = "i2np.udp.enable"; private final static String PROP_ENABLE_NTCP = "i2np.ntcp.enable"; private final static String DEFAULT_ENABLE_NTCP = "true"; @@ -66,8 +65,6 @@ public class TransportManager implements TransportEventListener { transport.setListener(null); } - static final boolean ALLOW_TCP = false; - private void configTransports() { String enableUDP = _context.router().getConfigSetting(PROP_ENABLE_UDP); if (enableUDP == null) @@ -77,13 +74,16 @@ public class TransportManager implements TransportEventListener { udp.setListener(this); _transports.add(udp); } - enableNTCP(_context); - NTCPTransport ntcp = new NTCPTransport(_context); - ntcp.setListener(this); - _transports.add(ntcp); + if (enableNTCP(_context)) { + NTCPTransport ntcp = new NTCPTransport(_context); + ntcp.setListener(this); + _transports.add(ntcp); + } + if (_transports.size() <= 0) + _log.log(Log.CRIT, "No transports are enabled"); } - static boolean enableNTCP(RouterContext ctx) { + public static boolean enableNTCP(RouterContext ctx) { String enableNTCP = ctx.router().getConfigSetting(PROP_ENABLE_NTCP); if (enableNTCP == null) enableNTCP = DEFAULT_ENABLE_NTCP; diff --git a/router/java/src/net/i2p/router/tunnel/FragmentHandler.java b/router/java/src/net/i2p/router/tunnel/FragmentHandler.java index 0637440016324f402c90cac7421e8e30cd1075b5..5a97956b9aee0bb8d5825eefdcfc6f7891bd711f 100644 --- a/router/java/src/net/i2p/router/tunnel/FragmentHandler.java +++ b/router/java/src/net/i2p/router/tunnel/FragmentHandler.java @@ -372,6 +372,8 @@ public class FragmentHandler { int fragmentCount = msg.getFragmentCount(); // toByteArray destroys the contents of the message completely byte data[] = msg.toByteArray(); + if (data == null) + throw new I2NPMessageException("null data"); // fragments already released??? if (_log.shouldLog(Log.DEBUG)) _log.debug("RECV(" + data.length + "): " + Base64.encode(data) + " " + _context.sha().calculateHash(data).toBase64()); diff --git a/router/java/src/net/i2p/router/tunnel/FragmentedMessage.java b/router/java/src/net/i2p/router/tunnel/FragmentedMessage.java index 78fba7e5b30068fd60c9384e0f5845a51050ad3f..d26c691b79344dd2b2e16591a94d1392ffd4537a 100644 --- a/router/java/src/net/i2p/router/tunnel/FragmentedMessage.java +++ b/router/java/src/net/i2p/router/tunnel/FragmentedMessage.java @@ -189,6 +189,9 @@ public class FragmentedMessage { int size = 0; for (int i = 0; i <= _highFragmentNum; i++) { ByteArray ba = _fragments[i]; + // NPE seen here, root cause unknown + if (ba == null) + throw new IllegalStateException("wtf, don't get the completed size when we're not complete - null fragment i=" + i + " of " + _highFragmentNum); size += ba.getValid(); } return size;