From fef1440865b6d0561c022d02034acb0a843b8238 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sat, 20 Oct 2012 17:28:00 +0000 Subject: [PATCH] * Transport: - Add a simple network monitor - Add new reachability state for network disconnected - Prevent any tunnel building when disconnected (ticket #519) - Don't unleash watchdog when disconnected --- .../src/net/i2p/router/web/SummaryHelper.java | 2 + .../src/net/i2p/router/CommSystemFacade.java | 10 ++++- router/java/src/net/i2p/router/Router.java | 2 + .../net/i2p/router/tasks/RouterWatchdog.java | 15 ++++--- .../transport/CommSystemFacadeImpl.java | 42 +++++++++++++++++-- .../i2p/router/tunnel/pool/BuildExecutor.java | 3 ++ 6 files changed, 63 insertions(+), 11 deletions(-) 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 99a64df949..1fe43f0bfe 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java @@ -171,6 +171,8 @@ public class SummaryHelper extends HelperBase { //if (_context.router().getRouterInfo().getCapabilities().indexOf('O') >= 0) // return _("WARN-Firewalled and Fast"); return _("Firewalled"); + case CommSystemFacade.STATUS_DISCONNECTED: + return _("Disconnected - check network cable"); case CommSystemFacade.STATUS_HOSED: return _("ERR-UDP Port In Use - Set i2np.udp.internalPort=xxxx in advanced config and restart"); case CommSystemFacade.STATUS_UNKNOWN: // fallthrough diff --git a/router/java/src/net/i2p/router/CommSystemFacade.java b/router/java/src/net/i2p/router/CommSystemFacade.java index 9bc1ae5356..82e73c2e10 100644 --- a/router/java/src/net/i2p/router/CommSystemFacade.java +++ b/router/java/src/net/i2p/router/CommSystemFacade.java @@ -81,6 +81,7 @@ public abstract class CommSystemFacade implements Service { * Tell other transports our address changed */ public void notifyReplaceAddress(RouterAddress UDPAddr) {} + /** * These must be increasing in "badness" (see TransportManager.java), * but UNKNOWN must be last. @@ -99,14 +100,19 @@ public abstract class CommSystemFacade implements Service { * cannot receive unsolicited connections */ public static final short STATUS_REJECT_UNSOLICITED = 2; + /** + * We have no network interface at all + * @since 0.9.4 + */ + public static final short STATUS_DISCONNECTED = 3; /** * Our detection system is broken (SSU bind port failed) */ - public static final short STATUS_HOSED = 3; + public static final short STATUS_HOSED = 4; /** * Our reachability is unknown */ - public static final short STATUS_UNKNOWN = 4; + public static final short STATUS_UNKNOWN = 5; } diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index 8b2a414f1d..725ca2779b 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -619,6 +619,8 @@ public class Router implements RouterClock.ClockShiftListener { case CommSystemFacade.STATUS_REJECT_UNSOLICITED: ri.addCapability(CAPABILITY_UNREACHABLE); break; + case CommSystemFacade.STATUS_DISCONNECTED: + case CommSystemFacade.STATUS_HOSED: case CommSystemFacade.STATUS_UNKNOWN: // no explicit capability break; diff --git a/router/java/src/net/i2p/router/tasks/RouterWatchdog.java b/router/java/src/net/i2p/router/tasks/RouterWatchdog.java index 233c3bd7a0..5d54b426e4 100644 --- a/router/java/src/net/i2p/router/tasks/RouterWatchdog.java +++ b/router/java/src/net/i2p/router/tasks/RouterWatchdog.java @@ -4,6 +4,7 @@ import java.io.File; import net.i2p.data.DataHelper; import net.i2p.router.Job; +import net.i2p.router.CommSystemFacade; import net.i2p.router.Router; import net.i2p.router.RouterContext; import net.i2p.router.util.EventLog; @@ -129,11 +130,15 @@ public class RouterWatchdog implements Runnable { boolean ok = verifyJobQueueLiveliness(); // If we aren't connected to the network that's why there's nobody to talk to long netErrors = 0; - RateStat rs = _context.statManager().getRate("udp.sendException"); - if (rs != null) { - Rate r = rs.getRate(60*1000); - if (r != null) - netErrors = r.getLastEventCount(); + if (_context.commSystem().getReachabilityStatus() == CommSystemFacade.STATUS_DISCONNECTED) { + netErrors = 10; + } else { + RateStat rs = _context.statManager().getRate("udp.sendException"); + if (rs != null) { + Rate r = rs.getRate(60*1000); + if (r != null) + netErrors = r.getLastEventCount(); + } } ok = ok && (verifyClientLiveliness() || netErrors >= 5); diff --git a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java index 29f3a23d4a..4457bb80a9 100644 --- a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java +++ b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java @@ -31,21 +31,26 @@ import net.i2p.router.transport.ntcp.NTCPAddress; import net.i2p.router.transport.ntcp.NTCPTransport; import net.i2p.router.transport.udp.UDPAddress; import net.i2p.router.transport.udp.UDPTransport; +import net.i2p.util.Addresses; import net.i2p.util.Log; import net.i2p.util.SimpleScheduler; import net.i2p.util.SimpleTimer; +import net.i2p.util.SimpleTimer2; import net.i2p.util.Translate; public class CommSystemFacadeImpl extends CommSystemFacade { private final Log _log; private final RouterContext _context; private TransportManager _manager; - private GeoIP _geoIP; + private final GeoIP _geoIP; + private volatile boolean _netMonitorStatus; public CommSystemFacadeImpl(RouterContext context) { _context = context; _log = _context.logManager().getLog(CommSystemFacadeImpl.class); _context.statManager().createRateStat("transport.getBidsJobTime", "How long does it take?", "Transport", new long[] { 10*60*1000l }); + _netMonitorStatus = true; + _geoIP = new GeoIP(_context); startGeoIP(); } @@ -54,6 +59,7 @@ public class CommSystemFacadeImpl extends CommSystemFacade { _manager = new TransportManager(_context); _manager.startListening(); startTimestamper(); + startNetMonitor(); } /** @@ -169,8 +175,12 @@ public class CommSystemFacadeImpl extends CommSystemFacade { @Override public short getReachabilityStatus() { if (_manager == null) return STATUS_UNKNOWN; - if (_context.router().isHidden()) return STATUS_OK; - return _manager.getReachabilityStatus(); + if (!_netMonitorStatus) + return STATUS_DISCONNECTED; + short rv = _manager.getReachabilityStatus(); + if (rv != STATUS_HOSED && _context.router().isHidden()) + return STATUS_OK; + return rv; } @Override public void recheckReachability() { _manager.recheckReachability(); } @@ -416,7 +426,6 @@ public class CommSystemFacadeImpl extends CommSystemFacade { private static final int START_DELAY = 5*60*1000; private static final int LOOKUP_TIME = 30*60*1000; private void startGeoIP() { - _geoIP = new GeoIP(_context); _context.simpleScheduler().addEvent(new QueueAll(), START_DELAY); } @@ -555,6 +564,7 @@ public class CommSystemFacadeImpl extends CommSystemFacade { private static final int TIME_START_DELAY = 5*60*1000; private static final int TIME_REPEAT_DELAY = 10*60*1000; + /** @since 0.7.12 */ private void startTimestamper() { _context.simpleScheduler().addPeriodicEvent(new Timestamper(), TIME_START_DELAY, TIME_REPEAT_DELAY); @@ -579,4 +589,28 @@ public class CommSystemFacadeImpl extends CommSystemFacade { _context.clock().setOffset(newOffset); } } + + /** @since 0.9.4 */ + private void startNetMonitor() { + new NetMonitor(); + } + + /** + * Simple check to see if we have a network connection + * @since 0.9.4 + */ + private class NetMonitor extends SimpleTimer2.TimedEvent { + private static final long SHORT_DELAY = 15*1000; + private static final long LONG_DELAY = 3*60*1000; + + public NetMonitor() { + super(_context.simpleTimer2(), 0); + } + + public void timeReached() { + boolean good = Addresses.isConnected(); + _netMonitorStatus = good; + reschedule(good ? LONG_DELAY : SHORT_DELAY); + } + } } 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 6303b385c4..2c3a5ffd72 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java +++ b/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java @@ -10,6 +10,7 @@ import java.util.concurrent.ConcurrentHashMap; import net.i2p.data.Hash; import net.i2p.data.i2np.I2NPMessage; import net.i2p.data.RouterInfo; +import net.i2p.router.CommSystemFacade; import net.i2p.router.RouterContext; import net.i2p.router.TunnelManagerFacade; import net.i2p.stat.Rate; @@ -104,6 +105,8 @@ class BuildExecutor implements Runnable { } private int allowed() { + if (_context.commSystem().getReachabilityStatus() == CommSystemFacade.STATUS_DISCONNECTED) + return 0; int maxKBps = _context.bandwidthLimiter().getOutboundKBytesPerSecond(); int allowed = maxKBps / 6; // Max. 1 concurrent build per 6 KB/s outbound RateStat rs = _context.statManager().getRate("tunnel.buildRequestTime"); -- GitLab