* 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
This commit is contained in:
zzz
2012-10-20 17:28:00 +00:00
parent afd29715fa
commit fef1440865
6 changed files with 63 additions and 11 deletions

View File

@ -171,6 +171,8 @@ public class SummaryHelper extends HelperBase {
//if (_context.router().getRouterInfo().getCapabilities().indexOf('O') >= 0) //if (_context.router().getRouterInfo().getCapabilities().indexOf('O') >= 0)
// return _("WARN-Firewalled and Fast"); // return _("WARN-Firewalled and Fast");
return _("Firewalled"); return _("Firewalled");
case CommSystemFacade.STATUS_DISCONNECTED:
return _("Disconnected - check network cable");
case CommSystemFacade.STATUS_HOSED: case CommSystemFacade.STATUS_HOSED:
return _("ERR-UDP Port In Use - Set i2np.udp.internalPort=xxxx in advanced config and restart"); return _("ERR-UDP Port In Use - Set i2np.udp.internalPort=xxxx in advanced config and restart");
case CommSystemFacade.STATUS_UNKNOWN: // fallthrough case CommSystemFacade.STATUS_UNKNOWN: // fallthrough

View File

@ -81,6 +81,7 @@ public abstract class CommSystemFacade implements Service {
* Tell other transports our address changed * Tell other transports our address changed
*/ */
public void notifyReplaceAddress(RouterAddress UDPAddr) {} public void notifyReplaceAddress(RouterAddress UDPAddr) {}
/** /**
* These must be increasing in "badness" (see TransportManager.java), * These must be increasing in "badness" (see TransportManager.java),
* but UNKNOWN must be last. * but UNKNOWN must be last.
@ -99,14 +100,19 @@ public abstract class CommSystemFacade implements Service {
* cannot receive unsolicited connections * cannot receive unsolicited connections
*/ */
public static final short STATUS_REJECT_UNSOLICITED = 2; 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) * 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 * Our reachability is unknown
*/ */
public static final short STATUS_UNKNOWN = 4; public static final short STATUS_UNKNOWN = 5;
} }

View File

@ -619,6 +619,8 @@ public class Router implements RouterClock.ClockShiftListener {
case CommSystemFacade.STATUS_REJECT_UNSOLICITED: case CommSystemFacade.STATUS_REJECT_UNSOLICITED:
ri.addCapability(CAPABILITY_UNREACHABLE); ri.addCapability(CAPABILITY_UNREACHABLE);
break; break;
case CommSystemFacade.STATUS_DISCONNECTED:
case CommSystemFacade.STATUS_HOSED:
case CommSystemFacade.STATUS_UNKNOWN: case CommSystemFacade.STATUS_UNKNOWN:
// no explicit capability // no explicit capability
break; break;

View File

@ -4,6 +4,7 @@ import java.io.File;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.router.Job; import net.i2p.router.Job;
import net.i2p.router.CommSystemFacade;
import net.i2p.router.Router; import net.i2p.router.Router;
import net.i2p.router.RouterContext; import net.i2p.router.RouterContext;
import net.i2p.router.util.EventLog; import net.i2p.router.util.EventLog;
@ -129,11 +130,15 @@ public class RouterWatchdog implements Runnable {
boolean ok = verifyJobQueueLiveliness(); boolean ok = verifyJobQueueLiveliness();
// If we aren't connected to the network that's why there's nobody to talk to // If we aren't connected to the network that's why there's nobody to talk to
long netErrors = 0; long netErrors = 0;
RateStat rs = _context.statManager().getRate("udp.sendException"); if (_context.commSystem().getReachabilityStatus() == CommSystemFacade.STATUS_DISCONNECTED) {
if (rs != null) { netErrors = 10;
Rate r = rs.getRate(60*1000); } else {
if (r != null) RateStat rs = _context.statManager().getRate("udp.sendException");
netErrors = r.getLastEventCount(); if (rs != null) {
Rate r = rs.getRate(60*1000);
if (r != null)
netErrors = r.getLastEventCount();
}
} }
ok = ok && (verifyClientLiveliness() || netErrors >= 5); ok = ok && (verifyClientLiveliness() || netErrors >= 5);

View File

@ -31,21 +31,26 @@ import net.i2p.router.transport.ntcp.NTCPAddress;
import net.i2p.router.transport.ntcp.NTCPTransport; import net.i2p.router.transport.ntcp.NTCPTransport;
import net.i2p.router.transport.udp.UDPAddress; import net.i2p.router.transport.udp.UDPAddress;
import net.i2p.router.transport.udp.UDPTransport; import net.i2p.router.transport.udp.UDPTransport;
import net.i2p.util.Addresses;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.SimpleScheduler; import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer; import net.i2p.util.SimpleTimer;
import net.i2p.util.SimpleTimer2;
import net.i2p.util.Translate; import net.i2p.util.Translate;
public class CommSystemFacadeImpl extends CommSystemFacade { public class CommSystemFacadeImpl extends CommSystemFacade {
private final Log _log; private final Log _log;
private final RouterContext _context; private final RouterContext _context;
private TransportManager _manager; private TransportManager _manager;
private GeoIP _geoIP; private final GeoIP _geoIP;
private volatile boolean _netMonitorStatus;
public CommSystemFacadeImpl(RouterContext context) { public CommSystemFacadeImpl(RouterContext context) {
_context = context; _context = context;
_log = _context.logManager().getLog(CommSystemFacadeImpl.class); _log = _context.logManager().getLog(CommSystemFacadeImpl.class);
_context.statManager().createRateStat("transport.getBidsJobTime", "How long does it take?", "Transport", new long[] { 10*60*1000l }); _context.statManager().createRateStat("transport.getBidsJobTime", "How long does it take?", "Transport", new long[] { 10*60*1000l });
_netMonitorStatus = true;
_geoIP = new GeoIP(_context);
startGeoIP(); startGeoIP();
} }
@ -54,6 +59,7 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
_manager = new TransportManager(_context); _manager = new TransportManager(_context);
_manager.startListening(); _manager.startListening();
startTimestamper(); startTimestamper();
startNetMonitor();
} }
/** /**
@ -169,8 +175,12 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
@Override @Override
public short getReachabilityStatus() { public short getReachabilityStatus() {
if (_manager == null) return STATUS_UNKNOWN; if (_manager == null) return STATUS_UNKNOWN;
if (_context.router().isHidden()) return STATUS_OK; if (!_netMonitorStatus)
return _manager.getReachabilityStatus(); return STATUS_DISCONNECTED;
short rv = _manager.getReachabilityStatus();
if (rv != STATUS_HOSED && _context.router().isHidden())
return STATUS_OK;
return rv;
} }
@Override @Override
public void recheckReachability() { _manager.recheckReachability(); } 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 START_DELAY = 5*60*1000;
private static final int LOOKUP_TIME = 30*60*1000; private static final int LOOKUP_TIME = 30*60*1000;
private void startGeoIP() { private void startGeoIP() {
_geoIP = new GeoIP(_context);
_context.simpleScheduler().addEvent(new QueueAll(), START_DELAY); _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_START_DELAY = 5*60*1000;
private static final int TIME_REPEAT_DELAY = 10*60*1000; private static final int TIME_REPEAT_DELAY = 10*60*1000;
/** @since 0.7.12 */ /** @since 0.7.12 */
private void startTimestamper() { private void startTimestamper() {
_context.simpleScheduler().addPeriodicEvent(new Timestamper(), TIME_START_DELAY, TIME_REPEAT_DELAY); _context.simpleScheduler().addPeriodicEvent(new Timestamper(), TIME_START_DELAY, TIME_REPEAT_DELAY);
@ -579,4 +589,28 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
_context.clock().setOffset(newOffset); _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);
}
}
} }

View File

@ -10,6 +10,7 @@ import java.util.concurrent.ConcurrentHashMap;
import net.i2p.data.Hash; import net.i2p.data.Hash;
import net.i2p.data.i2np.I2NPMessage; import net.i2p.data.i2np.I2NPMessage;
import net.i2p.data.RouterInfo; import net.i2p.data.RouterInfo;
import net.i2p.router.CommSystemFacade;
import net.i2p.router.RouterContext; import net.i2p.router.RouterContext;
import net.i2p.router.TunnelManagerFacade; import net.i2p.router.TunnelManagerFacade;
import net.i2p.stat.Rate; import net.i2p.stat.Rate;
@ -104,6 +105,8 @@ class BuildExecutor implements Runnable {
} }
private int allowed() { private int allowed() {
if (_context.commSystem().getReachabilityStatus() == CommSystemFacade.STATUS_DISCONNECTED)
return 0;
int maxKBps = _context.bandwidthLimiter().getOutboundKBytesPerSecond(); int maxKBps = _context.bandwidthLimiter().getOutboundKBytesPerSecond();
int allowed = maxKBps / 6; // Max. 1 concurrent build per 6 KB/s outbound int allowed = maxKBps / 6; // Max. 1 concurrent build per 6 KB/s outbound
RateStat rs = _context.statManager().getRate("tunnel.buildRequestTime"); RateStat rs = _context.statManager().getRate("tunnel.buildRequestTime");