* 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)
// 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

View File

@ -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;
}

View File

@ -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;

View File

@ -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,12 +130,16 @@ 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;
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);

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.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);
}
}
}

View File

@ -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");