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 47a07c374..1b302ff0b 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java @@ -106,6 +106,9 @@ public class SummaryHelper extends HelperBase { public int getAllPeers() { return _context.netDb().getKnownRouters(); } public String getReachability() { + if (_context.router().getUptime() > 60*1000 && (!_context.router().gracefulShutdownInProgress()) && + !_context.clientManager().isAlive()) + return "ERR-Client Manager I2CP Error - check logs"; // not a router problem but the user should know if (!_context.clock().getUpdatedSuccessfully()) return "ERR-ClockSkew"; if (_context.router().isHidden()) diff --git a/apps/routerconsole/jsp/config.jsp b/apps/routerconsole/jsp/config.jsp index 132bd5315..ae357d69f 100644 --- a/apps/routerconsole/jsp/config.jsp +++ b/apps/routerconsole/jsp/config.jsp @@ -112,6 +112,7 @@ if you open up your port (generally 8887) to both UDP and TCP, and enable inbound TCP above. If you think you have opened up your firewall and I2P still thinks you are firewalled, remember that you may have multiple firewalls, for example both software packages and external hardware routers. + If there is an error, the logs may also help diagnose the problem.


diff --git a/router/java/src/net/i2p/router/ClientManagerFacade.java b/router/java/src/net/i2p/router/ClientManagerFacade.java index 07f6e561f..2e441fefe 100644 --- a/router/java/src/net/i2p/router/ClientManagerFacade.java +++ b/router/java/src/net/i2p/router/ClientManagerFacade.java @@ -72,6 +72,7 @@ public abstract class ClientManagerFacade implements Service { public abstract void messageReceived(ClientMessage msg); public boolean verifyClientLiveliness() { return true; } + public boolean isAlive() { return true; } /** * Does the client specified want their leaseSet published? */ diff --git a/router/java/src/net/i2p/router/client/ClientListenerRunner.java b/router/java/src/net/i2p/router/client/ClientListenerRunner.java index 074b161df..38105e9c9 100644 --- a/router/java/src/net/i2p/router/client/ClientListenerRunner.java +++ b/router/java/src/net/i2p/router/client/ClientListenerRunner.java @@ -31,7 +31,7 @@ public class ClientListenerRunner implements Runnable { private int _port; private boolean _bindAllInterfaces; private boolean _running; - private long _nextFailDelay = 1000; + private boolean _listening; public static final String BIND_ALL_INTERFACES = "i2cp.tcp.bindAllInterfaces"; @@ -41,6 +41,7 @@ public class ClientListenerRunner implements Runnable { _manager = manager; _port = port; _running = false; + _listening = false; String val = context.getProperty(BIND_ALL_INTERFACES, "False"); _bindAllInterfaces = Boolean.valueOf(val).booleanValue(); @@ -48,6 +49,7 @@ public class ClientListenerRunner implements Runnable { public void setPort(int port) { _port = port; } public int getPort() { return _port; } + public boolean isListening() { return _running && _listening; } /** * Start up the socket listener, listens for connections, and @@ -58,7 +60,7 @@ public class ClientListenerRunner implements Runnable { */ public void runServer() { _running = true; - int curDelay = 0; + int curDelay = 1000; while (_running) { try { if (_bindAllInterfaces) { @@ -77,7 +79,8 @@ public class ClientListenerRunner implements Runnable { if (_log.shouldLog(Log.DEBUG)) _log.debug("ServerSocket created, before accept: " + _socket); - curDelay = 0; + curDelay = 1000; + _listening = true; while (_running) { try { Socket socket = _socket.accept(); @@ -96,6 +99,7 @@ public class ClientListenerRunner implements Runnable { } catch (Throwable t) { if (_context.router().isAlive()) _log.error("Fatal error running client listener - killing the thread!", t); + _listening = false; return; } } @@ -104,6 +108,7 @@ public class ClientListenerRunner implements Runnable { _log.error("Error listening on port " + _port, ioe); } + _listening = false; if (_socket != null) { try { _socket.close(); } catch (IOException ioe) {} _socket = null; @@ -111,14 +116,16 @@ public class ClientListenerRunner implements Runnable { if (!_context.router().isAlive()) break; - _log.error("Error listening, waiting " + _nextFailDelay + "ms before we try again"); - try { Thread.sleep(_nextFailDelay); } catch (InterruptedException ie) {} - curDelay += _nextFailDelay; - _nextFailDelay *= 5; + if (curDelay < 60*1000) + _log.error("Error listening, waiting " + (curDelay/1000) + "s before we try again"); + else + _log.log(Log.CRIT, "I2CP error listening to port " + _port + " - is another I2P instance running? Resolve conflicts and restart"); + try { Thread.sleep(curDelay); } catch (InterruptedException ie) {} + curDelay = Math.min(curDelay*3, 60*1000); } if (_context.router().isAlive()) - _log.error("CANCELING I2CP LISTEN. delay = " + curDelay, new Exception("I2CP Listen cancelled!!!")); + _log.error("CANCELING I2CP LISTEN", new Exception("I2CP Listen cancelled!!!")); _running = false; } diff --git a/router/java/src/net/i2p/router/client/ClientManager.java b/router/java/src/net/i2p/router/client/ClientManager.java index 18c9c7742..9b5eb7c4c 100644 --- a/router/java/src/net/i2p/router/client/ClientManager.java +++ b/router/java/src/net/i2p/router/client/ClientManager.java @@ -108,6 +108,8 @@ public class ClientManager { } } + public boolean isAlive() { return _listener.isListening(); } + public void registerConnection(ClientConnectionRunner runner) { synchronized (_pendingRunners) { _pendingRunners.add(runner); diff --git a/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java b/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java index 796a098a9..51b8b4cb2 100644 --- a/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java +++ b/router/java/src/net/i2p/router/client/ClientManagerFacadeImpl.java @@ -74,6 +74,8 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade { startup(); } + public boolean isAlive() { return _manager != null && _manager.isAlive(); } + private static final long MAX_TIME_TO_REBUILD = 10*60*1000; public boolean verifyClientLiveliness() { if (_manager == null) return true;