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 a3280ac446..886ba6abb6 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/NetDbHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/NetDbHelper.java @@ -10,17 +10,21 @@ import net.i2p.router.RouterContext; public class NetDbHelper extends HelperBase { private String _routerPrefix; private boolean _full = false; + private boolean _lease = false; public NetDbHelper() {} public void setRouter(String r) { _routerPrefix = r; } - public void setFull(String f) { _full = "1".equals(f); }; + public void setFull(String f) { _full = "1".equals(f); } + public void setLease(String l) { _lease = "1".equals(l); } public String getNetDbSummary() { try { if (_out != null) { if (_routerPrefix != null) _context.netDb().renderRouterInfoHTML(_out, _routerPrefix); + else if (_lease) + _context.netDb().renderLeaseSetHTML(_out); else _context.netDb().renderStatusHTML(_out, _full); return ""; @@ -28,6 +32,8 @@ public class NetDbHelper extends HelperBase { ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024); if (_routerPrefix != null) _context.netDb().renderRouterInfoHTML(new OutputStreamWriter(baos), _routerPrefix); + else if (_lease) + _context.netDb().renderLeaseSetHTML(new OutputStreamWriter(baos)); else _context.netDb().renderStatusHTML(new OutputStreamWriter(baos), _full); return new String(baos.toByteArray()); diff --git a/apps/routerconsole/jsp/netdb.jsp b/apps/routerconsole/jsp/netdb.jsp index 08a1377d37..392888bc67 100644 --- a/apps/routerconsole/jsp/netdb.jsp +++ b/apps/routerconsole/jsp/netdb.jsp @@ -16,6 +16,7 @@ " /> " /> + " /> diff --git a/router/java/src/net/i2p/router/NetworkDatabaseFacade.java b/router/java/src/net/i2p/router/NetworkDatabaseFacade.java index e1169b455a..ded9bee26a 100644 --- a/router/java/src/net/i2p/router/NetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/NetworkDatabaseFacade.java @@ -58,5 +58,6 @@ public abstract class NetworkDatabaseFacade implements Service { public int getKnownRouters() { return 0; } public int getKnownLeaseSets() { return 0; } public void renderRouterInfoHTML(Writer out, String s) throws IOException {} + public void renderLeaseSetHTML(Writer out) throws IOException {} public void renderStatusHTML(Writer out, boolean b) throws IOException {} } diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index a4a707926e..c9a95dd552 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -685,6 +685,7 @@ public class Router { out.write("\n
\n"); + _context.netDb().renderLeaseSetHTML(out); _context.netDb().renderStatusHTML(out); buf.setLength(0); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java index 9b1a1c7acd..b980170227 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java @@ -115,11 +115,13 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { protected final static int MIN_REMAINING_ROUTERS = 25; /** - * dont accept any dbDtore of a router over 24 hours old (unless we dont - * know anyone or just started up) + * limits for accepting a dbDtore of a router (unless we dont + * know anyone or just started up) -- see validate() below */ private final static long ROUTER_INFO_EXPIRATION = 3*24*60*60*1000l; + private final static long ROUTER_INFO_EXPIRATION_MIN = 3*60*60*1000l; private final static long ROUTER_INFO_EXPIRATION_SHORT = 90*60*1000l; + private final static long ROUTER_INFO_EXPIRATION_FLOODFILL = 45*60*1000l; private final static long EXPLORE_JOB_DELAY = 10*60*1000l; private final static long PUBLISH_JOB_DELAY = 5*60*1000l; @@ -624,7 +626,22 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { */ String validate(Hash key, RouterInfo routerInfo) throws IllegalArgumentException { long now = _context.clock().now(); - + boolean upLongEnough = _context.router().getUptime() > 60*60*1000; + // Once we're over 300 routers, reduce the expiration time down from the default, + // as a crude way of limiting memory usage. + // i.e. at 600 routers the expiration time will be about half the default, etc. + // And if we're floodfill, we can keep the expiration really short, since + // we are always getting the latest published to us. + // As the net grows this won't be sufficient, and we'll have to implement + // flushing some from memory, while keeping all on disk. + long adjustedExpiration; + if (FloodfillNetworkDatabaseFacade.floodfillEnabled(_context)) + adjustedExpiration = ROUTER_INFO_EXPIRATION_FLOODFILL; + else + adjustedExpiration = Math.min(ROUTER_INFO_EXPIRATION, + ROUTER_INFO_EXPIRATION_MIN + + ((ROUTER_INFO_EXPIRATION - ROUTER_INFO_EXPIRATION_MIN) * 300 / (_kb.size() + 1))); + if (!key.equals(routerInfo.getIdentity().getHash())) { if (_log.shouldLog(Log.WARN)) _log.warn("Invalid store attempt! key does not match routerInfo.identity! key = " + key + ", router = " + routerInfo); @@ -633,7 +650,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { if (_log.shouldLog(Log.WARN)) _log.warn("Invalid routerInfo signature! forged router structure! router = " + routerInfo); return "Invalid routerInfo signature on " + key.toBase64(); - } else if (!routerInfo.isCurrent(ROUTER_INFO_EXPIRATION) && (_context.router().getUptime() > 60*60*1000) ) { + } else if (upLongEnough && !routerInfo.isCurrent(adjustedExpiration)) { if (routerInfo.getNetworkId() != Router.NETWORK_ID) { _context.shitlist().shitlistRouter(key, "Peer is not in our network"); return "Peer is not in our network (" + routerInfo.getNetworkId() + ", wants " @@ -661,10 +678,10 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { String rv = "Peer " + key.toBase64() + " is from another network, not accepting it (id=" + routerInfo.getNetworkId() + ", want " + Router.NETWORK_ID + ")"; return rv; - } else if ( (_context.router().getUptime() > 60*60*1000) && (routerInfo.getPublished() < now - 2*24*60*60*1000l) ) { + } else if (upLongEnough && (routerInfo.getPublished() < now - 2*24*60*60*1000l) ) { long age = _context.clock().now() - routerInfo.getPublished(); return "Peer " + key.toBase64() + " published " + DataHelper.formatDuration(age) + " ago"; - } else if (!routerInfo.isCurrent(ROUTER_INFO_EXPIRATION_SHORT) && (_context.router().getUptime() > 60*60*1000) ) { + } else if (upLongEnough && !routerInfo.isCurrent(ROUTER_INFO_EXPIRATION_SHORT)) { if (routerInfo.getAddresses().size() <= 0) return "Peer " + key.toBase64() + " published > 90m ago with no addresses"; RouterAddress ra = routerInfo.getTargetAddress("SSU"); @@ -901,23 +918,13 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { } @Override - public void renderStatusHTML(Writer out, boolean full) throws IOException { - int size = getKnownRouters() * 512; - if (full) - size *= 4; - StringBuffer buf = new StringBuffer(size); + public void renderLeaseSetHTML(Writer out) throws IOException { + StringBuffer buf = new StringBuffer(4*1024); buf.append("

Network Database Contents

\n"); - if (!_initialized) { - buf.append("Not initialized\n"); - out.write(buf.toString()); - out.flush(); - return; - } + buf.append("View RouterInfo"); + buf.append("

LeaseSets

\n"); Set leases = new TreeSet(new LeaseSetComparator()); leases.addAll(getLeases()); - buf.append("

Leases

\n"); - out.write(buf.toString()); - buf.setLength(0); long now = _context.clock().now(); for (Iterator iter = leases.iterator(); iter.hasNext(); ) { LeaseSet ls = (LeaseSet)iter.next(); @@ -957,7 +964,25 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { out.write(buf.toString()); buf.setLength(0); } + out.write(buf.toString()); + out.flush(); + } + + @Override + public void renderStatusHTML(Writer out, boolean full) throws IOException { + int size = getKnownRouters() * 512; + if (full) + size *= 4; + StringBuffer buf = new StringBuffer(size); + out.write("

Network Database Contents

\n"); + if (!_initialized) { + buf.append("Not initialized\n"); + out.write(buf.toString()); + out.flush(); + return; + } + out.write("View LeaseSets"); Hash us = _context.routerHash(); out.write("

Routers (