From 73cf3fb2998934f72dabc92b0950d3869dc0f976 Mon Sep 17 00:00:00 2001 From: complication Date: Sun, 8 Oct 2006 22:52:59 +0000 Subject: [PATCH] 2006-10-08 Complication * Add a framed average peer clock skew calculator * Add config property "router.clockOffsetSanityCheck" to determine if NTP-suggested clock offsets get sanity checked (default "true") * Reject NTP-suggested clock offsets if they'd increase peer clock skew by more than 5 seconds, or make it more than 20 seconds total * Decrease log level in getMedianPeerClockSkew() --- history.txt | 10 +++- .../src/net/i2p/router/CommSystemFacade.java | 6 +++ .../java/src/net/i2p/router/RouterClock.java | 32 +++++++++++-- .../src/net/i2p/router/RouterVersion.java | 4 +- .../transport/CommSystemFacadeImpl.java | 46 ++++++++++++++++++- 5 files changed, 90 insertions(+), 8 deletions(-) diff --git a/history.txt b/history.txt index e6ef9e03d..a628e3668 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,12 @@ -$Id: history.txt,v 1.529 2006-09-27 01:00:33 jrandom Exp $ +$Id: history.txt,v 1.530 2006-09-29 18:54:19 zzz Exp $ + +2006-10-08 Complication + * Add a framed average peer clock skew calculator + * Add config property "router.clockOffsetSanityCheck" to determine + if NTP-suggested clock offsets get sanity checked (default "true") + * Reject NTP-suggested clock offsets if they'd increase peer clock skew + by more than 5 seconds, or make it more than 20 seconds total + * Decrease log level in getMedianPeerClockSkew() 2006-09-29 zzz * i2psnark: Second try at synchronization fix - synch addRequest() diff --git a/router/java/src/net/i2p/router/CommSystemFacade.java b/router/java/src/net/i2p/router/CommSystemFacade.java index e0337906c..1eb5dea70 100644 --- a/router/java/src/net/i2p/router/CommSystemFacade.java +++ b/router/java/src/net/i2p/router/CommSystemFacade.java @@ -39,6 +39,12 @@ public abstract class CommSystemFacade implements Service { */ public Long getMedianPeerClockSkew() { return null; } + /** + * Return framed average clock skew of connected peers in seconds, or null if we cannot answer. + * CommSystemFacadeImpl overrides this. + */ + public Long getFramedAveragePeerClockSkew(int percentToInclude) { return null; } + /** * Determine under what conditions we are remotely reachable. * diff --git a/router/java/src/net/i2p/router/RouterClock.java b/router/java/src/net/i2p/router/RouterClock.java index 06010d542..75d8b850e 100644 --- a/router/java/src/net/i2p/router/RouterClock.java +++ b/router/java/src/net/i2p/router/RouterClock.java @@ -31,9 +31,6 @@ public class RouterClock extends Clock { */ public void setOffset(long offsetMs, boolean force) { - // To test new routines, calculate median peer clock skew - Long medianPeerClockSkew = _context.commSystem().getMedianPeerClockSkew(); - if (false) return; long delta = offsetMs - _offset; if (!force) { @@ -56,7 +53,36 @@ public class RouterClock extends Clock { _alreadyChanged = true; return; } + + // If so configured, check sanity of proposed clock offset + if (Boolean.valueOf(_context.getProperty("router.clockOffsetSanityCheck","true")).booleanValue() == true) { + + // Try calculating peer clock skew + Long peerClockSkew = _context.commSystem().getFramedAveragePeerClockSkew(50); + + if (peerClockSkew != null) { + + // Predict the effect of applying the proposed clock offset + long currentPeerClockSkew = peerClockSkew.longValue(); + long predictedPeerClockSkew = currentPeerClockSkew + (delta / 1000l); + + // Fail sanity check if applying the offset would increase peer clock skew + if ((Math.abs(predictedPeerClockSkew) > (Math.abs(currentPeerClockSkew) + 5)) || + (Math.abs(predictedPeerClockSkew) > 20)) { + + getLog().error("Ignoring clock offset " + offsetMs + "ms (current " + _offset + + "ms) since it would increase peer clock skew from " + currentPeerClockSkew + + "s to " + predictedPeerClockSkew + "s. Broken server in pool.ntp.org?"); + return; + } else { + getLog().debug("Approving clock offset " + offsetMs + "ms (current " + _offset + + "ms) since it would decrease peer clock skew from " + currentPeerClockSkew + + "s to " + predictedPeerClockSkew + "s."); + } + } + } // check sanity } + if (_alreadyChanged) { if (delta > 15*1000) getLog().log(Log.CRIT, "Updating clock offset to " + offsetMs + "ms from " + _offset + "ms"); diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index ea898896e..b02c2d3e9 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -15,9 +15,9 @@ import net.i2p.CoreVersion; * */ public class RouterVersion { - public final static String ID = "$Revision: 1.464 $ $Date: 2006-09-27 01:00:37 $"; + public final static String ID = "$Revision: 1.465 $ $Date: 2006-09-29 18:54:17 $"; public final static String VERSION = "0.6.1.25"; - public final static long BUILD = 11; + public final static long BUILD = 12; public static void main(String args[]) { System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("Router ID: " + RouterVersion.ID); diff --git a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java index 21d8c6307..f802c7e3d 100644 --- a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java +++ b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java @@ -84,11 +84,53 @@ public class CommSystemFacadeImpl extends CommSystemFacade { Collections.sort(skews); // Pick out median Long medianPeerClockSkew = (Long) (skews.get(skews.size() / 2)); - if (_log.shouldLog(Log.WARN)) - _log.warn("Our median peer clock skew is " + medianPeerClockSkew + " s."); + if (_log.shouldLog(Log.INFO)) + _log.info("Our median peer clock skew is " + medianPeerClockSkew + " s."); return medianPeerClockSkew; } + /** + * Framed average clock skew of connected peers in seconds, or null if we cannot answer. + * Average is calculated over the middle "percentToInclude" peers. + */ + public Long getFramedAveragePeerClockSkew(int percentToInclude) { + if (_manager == null) { + if (_log.shouldLog(Log.INFO)) + _log.info("Returning null for framed averege peer clock skew (no transport manager)!"); + return null; + } + Vector skews = _manager.getClockSkews(); + if (skews == null) { + if (_log.shouldLog(Log.ERROR)) + _log.error("Returning null for framed average peer clock skew (no data)!"); + return null; + } + if (skews.size() < 5) { + if (_log.shouldLog(Log.ERROR)) + _log.error("Returning null for framed average peer clock skew (only " + skews.size() + " peers)!"); + return null; + } + // Going to calculate, sort them + Collections.sort(skews); + // Calculate frame size + int frameSize = (skews.size() * percentToInclude / 100); + int first = (skews.size() / 2) - (frameSize / 2); + int last = (skews.size() / 2) + (frameSize / 2); + // Sum skew values + long sum = 0; + for (int i = first; i < last; i++) { + long value = ((Long) (skews.get(i))).longValue(); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Adding clock skew " + i + " valued " + value + " s."); + sum = sum + value; + } + // Calculate average + Long framedAverageClockSkew = new Long(sum / frameSize); + if (_log.shouldLog(Log.INFO)) + _log.info("Our framed average peer clock skew is " + framedAverageClockSkew + " s."); + return framedAverageClockSkew; + } + public List getBids(OutNetMessage msg) { return _manager.getBids(msg); }