forked from I2P_Developers/i2p.i2p
* Clock: Cleanups and javadocs
* EepGet: Cleanups and javadocs * Reseed: Use the reseeder as a clock source
This commit is contained in:
@ -59,7 +59,6 @@ public class I2PSocketEepGet extends EepGet {
|
|||||||
// public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String postData) {
|
// public EepGet(I2PAppContext ctx, boolean shouldProxy, String proxyHost, int proxyPort, int numRetries, long minSize, long maxSize, String outputFile, OutputStream outputStream, String url, boolean allowCaching, String etag, String postData) {
|
||||||
super(ctx, false, null, -1, numRetries, minSize, maxSize, outputFile, outputStream, url, true, null, null);
|
super(ctx, false, null, -1, numRetries, minSize, maxSize, outputFile, outputStream, url, true, null, null);
|
||||||
_socketManager = mgr;
|
_socketManager = mgr;
|
||||||
_log = ctx.logManager().getLog(I2PSocketEepGet.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,11 +3,9 @@ package net.i2p.router.web;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.crypto.TrustedUpdate;
|
import net.i2p.crypto.TrustedUpdate;
|
||||||
@ -15,6 +13,7 @@ import net.i2p.data.DataHelper;
|
|||||||
import net.i2p.router.Router;
|
import net.i2p.router.Router;
|
||||||
import net.i2p.router.RouterContext;
|
import net.i2p.router.RouterContext;
|
||||||
import net.i2p.router.RouterVersion;
|
import net.i2p.router.RouterVersion;
|
||||||
|
import net.i2p.router.util.RFC822Date;
|
||||||
import net.i2p.util.EepGet;
|
import net.i2p.util.EepGet;
|
||||||
import net.i2p.util.EepHead;
|
import net.i2p.util.EepHead;
|
||||||
import net.i2p.util.FileUtil;
|
import net.i2p.util.FileUtil;
|
||||||
@ -73,7 +72,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
|||||||
if (_lastFetch == 0)
|
if (_lastFetch == 0)
|
||||||
_lastFetch = _lastUpdated;
|
_lastFetch = _lastUpdated;
|
||||||
if (_lastModified == null)
|
if (_lastModified == null)
|
||||||
_lastModified = to822Date(_lastFetch);
|
_lastModified = RFC822Date.to822Date(_lastFetch);
|
||||||
} else {
|
} else {
|
||||||
_lastUpdated = 0;
|
_lastUpdated = 0;
|
||||||
_lastFetch = 0;
|
_lastFetch = 0;
|
||||||
@ -212,7 +211,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
|||||||
String lastmod = get.getLastModified();
|
String lastmod = get.getLastModified();
|
||||||
if (lastmod != null) {
|
if (lastmod != null) {
|
||||||
if (!(_context.isRouterContext())) return;
|
if (!(_context.isRouterContext())) return;
|
||||||
long modtime = parse822Date(lastmod);
|
long modtime = RFC822Date.parse822Date(lastmod);
|
||||||
if (modtime <= 0) return;
|
if (modtime <= 0) return;
|
||||||
String lastUpdate = _context.getProperty(UpdateHandler.PROP_LAST_UPDATE_TIME);
|
String lastUpdate = _context.getProperty(UpdateHandler.PROP_LAST_UPDATE_TIME);
|
||||||
if (lastUpdate == null) {
|
if (lastUpdate == null) {
|
||||||
@ -251,44 +250,6 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
|||||||
handler.update();
|
handler.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* http://jimyjoshi.com/blog/2007/08/rfc822dateparsinginjava.html
|
|
||||||
* Apparently public domain
|
|
||||||
* Probably don't need all of these...
|
|
||||||
*/
|
|
||||||
private static final SimpleDateFormat rfc822DateFormats[] = new SimpleDateFormat[] {
|
|
||||||
new SimpleDateFormat("EEE, d MMM yy HH:mm:ss z", Locale.US),
|
|
||||||
new SimpleDateFormat("EEE, d MMM yy HH:mm z", Locale.US),
|
|
||||||
new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z", Locale.US),
|
|
||||||
new SimpleDateFormat("EEE, d MMM yyyy HH:mm z", Locale.US),
|
|
||||||
new SimpleDateFormat("d MMM yy HH:mm z", Locale.US),
|
|
||||||
new SimpleDateFormat("d MMM yy HH:mm:ss z", Locale.US),
|
|
||||||
new SimpleDateFormat("d MMM yyyy HH:mm z", Locale.US),
|
|
||||||
new SimpleDateFormat("d MMM yyyy HH:mm:ss z", Locale.US)
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* new Date(String foo) is deprecated, so let's do this the hard way
|
|
||||||
*
|
|
||||||
* @param s non-null
|
|
||||||
* @return -1 on failure
|
|
||||||
*/
|
|
||||||
public static long parse822Date(String s) {
|
|
||||||
for (int i = 0; i < rfc822DateFormats.length; i++) {
|
|
||||||
try {
|
|
||||||
Date date = rfc822DateFormats[i].parse(s);
|
|
||||||
if (date != null)
|
|
||||||
return date.getTime();
|
|
||||||
} catch (ParseException pe) {}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @since 0.8.2 */
|
|
||||||
private static String to822Date(long t) {
|
|
||||||
return (new SimpleDateFormat("d MMM yyyy HH:mm:ss z", Locale.US)).format(new Date(t));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String VERSION_STRING = "version=\"" + RouterVersion.VERSION + "\"";
|
private static final String VERSION_STRING = "version=\"" + RouterVersion.VERSION + "\"";
|
||||||
private static final String VERSION_PREFIX = "version=\"";
|
private static final String VERSION_PREFIX = "version=\"";
|
||||||
private void checkForUpdates() {
|
private void checkForUpdates() {
|
||||||
|
@ -4,6 +4,7 @@ import java.io.File;
|
|||||||
|
|
||||||
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.RFC822Date;
|
||||||
import net.i2p.util.EepGet;
|
import net.i2p.util.EepGet;
|
||||||
import net.i2p.util.FileUtil;
|
import net.i2p.util.FileUtil;
|
||||||
import net.i2p.util.I2PAppThread;
|
import net.i2p.util.I2PAppThread;
|
||||||
@ -101,7 +102,7 @@ public class UnsignedUpdateHandler extends UpdateHandler {
|
|||||||
String lastmod = _get.getLastModified();
|
String lastmod = _get.getLastModified();
|
||||||
long modtime = 0;
|
long modtime = 0;
|
||||||
if (lastmod != null)
|
if (lastmod != null)
|
||||||
modtime = NewsFetcher.parse822Date(lastmod);
|
modtime = RFC822Date.parse822Date(lastmod);
|
||||||
if (modtime <= 0)
|
if (modtime <= 0)
|
||||||
modtime = _context.clock().now();
|
modtime = _context.clock().now();
|
||||||
_context.router().setConfigSetting(PROP_LAST_UPDATE_TIME, "" + modtime);
|
_context.router().setConfigSetting(PROP_LAST_UPDATE_TIME, "" + modtime);
|
||||||
|
@ -15,6 +15,7 @@ import net.i2p.data.DataHelper;
|
|||||||
import net.i2p.router.Router;
|
import net.i2p.router.Router;
|
||||||
import net.i2p.router.RouterContext;
|
import net.i2p.router.RouterContext;
|
||||||
import net.i2p.router.RouterVersion;
|
import net.i2p.router.RouterVersion;
|
||||||
|
import net.i2p.router.util.RFC822Date;
|
||||||
import net.i2p.util.EepGet;
|
import net.i2p.util.EepGet;
|
||||||
import net.i2p.util.I2PAppThread;
|
import net.i2p.util.I2PAppThread;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
@ -271,7 +272,7 @@ public class UpdateHandler {
|
|||||||
String lastmod = _get.getLastModified();
|
String lastmod = _get.getLastModified();
|
||||||
long modtime = 0;
|
long modtime = 0;
|
||||||
if (lastmod != null)
|
if (lastmod != null)
|
||||||
modtime = NewsFetcher.parse822Date(lastmod);
|
modtime = RFC822Date.parse822Date(lastmod);
|
||||||
if (modtime <= 0)
|
if (modtime <= 0)
|
||||||
modtime = _context.clock().now();
|
modtime = _context.clock().now();
|
||||||
_context.router().setConfigSetting(PROP_LAST_UPDATE_TIME, "" + modtime);
|
_context.router().setConfigSetting(PROP_LAST_UPDATE_TIME, "" + modtime);
|
||||||
|
@ -4,6 +4,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.util.I2PThread;
|
import net.i2p.util.I2PThread;
|
||||||
@ -56,7 +57,7 @@ public class Timestamper implements Runnable {
|
|||||||
public Timestamper(I2PAppContext ctx, UpdateListener lsnr, boolean daemon) {
|
public Timestamper(I2PAppContext ctx, UpdateListener lsnr, boolean daemon) {
|
||||||
// moved here to prevent problems with synchronized statements.
|
// moved here to prevent problems with synchronized statements.
|
||||||
_servers = new ArrayList(3);
|
_servers = new ArrayList(3);
|
||||||
_listeners = new ArrayList(1);
|
_listeners = new CopyOnWriteArrayList();
|
||||||
// Don't bother starting a thread if we are disabled.
|
// Don't bother starting a thread if we are disabled.
|
||||||
// This means we no longer check every 5 minutes to see if we got enabled,
|
// This means we no longer check every 5 minutes to see if we got enabled,
|
||||||
// so the property must be set at startup.
|
// so the property must be set at startup.
|
||||||
@ -92,24 +93,16 @@ public class Timestamper implements Runnable {
|
|||||||
public boolean getIsDisabled() { return _disabled; }
|
public boolean getIsDisabled() { return _disabled; }
|
||||||
|
|
||||||
public void addListener(UpdateListener lsnr) {
|
public void addListener(UpdateListener lsnr) {
|
||||||
synchronized (_listeners) {
|
|
||||||
_listeners.add(lsnr);
|
_listeners.add(lsnr);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public void removeListener(UpdateListener lsnr) {
|
public void removeListener(UpdateListener lsnr) {
|
||||||
synchronized (_listeners) {
|
|
||||||
_listeners.remove(lsnr);
|
_listeners.remove(lsnr);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public int getListenerCount() {
|
public int getListenerCount() {
|
||||||
synchronized (_listeners) {
|
|
||||||
return _listeners.size();
|
return _listeners.size();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public UpdateListener getListener(int index) {
|
public UpdateListener getListener(int index) {
|
||||||
synchronized (_listeners) {
|
|
||||||
return _listeners.get(index);
|
return _listeners.get(index);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startTimestamper() {
|
private void startTimestamper() {
|
||||||
@ -257,11 +250,8 @@ public class Timestamper implements Runnable {
|
|||||||
*/
|
*/
|
||||||
private void stampTime(long now, int stratum) {
|
private void stampTime(long now, int stratum) {
|
||||||
long before = _context.clock().now();
|
long before = _context.clock().now();
|
||||||
synchronized (_listeners) {
|
for (UpdateListener lsnr : _listeners) {
|
||||||
for (int i = 0; i < _listeners.size(); i++) {
|
lsnr.setNow(now, stratum);
|
||||||
UpdateListener lsnr = _listeners.get(i);
|
|
||||||
lsnr.setNow(now, stratum);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Stamped the time as " + now + " (delta=" + (now-before) + ")");
|
_log.debug("Stamped the time as " + now + " (delta=" + (now-before) + ")");
|
||||||
|
@ -49,14 +49,22 @@ public class Clock implements Timestamper.UpdateListener {
|
|||||||
/** if the clock skewed changes by less than this, ignore the update (so we don't slide all over the place) */
|
/** if the clock skewed changes by less than this, ignore the update (so we don't slide all over the place) */
|
||||||
public final static long MIN_OFFSET_CHANGE = 5 * 1000;
|
public final static long MIN_OFFSET_CHANGE = 5 * 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify how far away from the "correct" time the computer is - a positive
|
||||||
|
* value means that the system time is slow, while a negative value means the system time is fast.
|
||||||
|
*
|
||||||
|
* @param offsetMs the delta from System.currentTimeMillis() (NOT the delta from now())
|
||||||
|
*/
|
||||||
public void setOffset(long offsetMs) {
|
public void setOffset(long offsetMs) {
|
||||||
setOffset(offsetMs, false);
|
setOffset(offsetMs, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify how far away from the "correct" time the computer is - a positive
|
* Specify how far away from the "correct" time the computer is - a positive
|
||||||
* value means that we are slow, while a negative value means we are fast.
|
* value means that the system time is slow, while a negative value means the system time is fast.
|
||||||
* Warning - overridden in RouterClock
|
* Warning - overridden in RouterClock
|
||||||
|
*
|
||||||
|
* @param offsetMs the delta from System.currentTimeMillis() (NOT the delta from now())
|
||||||
*/
|
*/
|
||||||
public void setOffset(long offsetMs, boolean force) {
|
public void setOffset(long offsetMs, boolean force) {
|
||||||
if (false) return;
|
if (false) return;
|
||||||
@ -101,6 +109,9 @@ public class Clock implements Timestamper.UpdateListener {
|
|||||||
fireOffsetChanged(delta);
|
fireOffsetChanged(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @return the current delta from System.currentTimeMillis() in milliseconds
|
||||||
|
*/
|
||||||
public long getOffset() {
|
public long getOffset() {
|
||||||
return _offset;
|
return _offset;
|
||||||
}
|
}
|
||||||
|
@ -28,21 +28,21 @@ import net.i2p.util.InternalSocket;
|
|||||||
* Bug: a malformed url http://example.i2p (no trailing '/') fails cryptically
|
* Bug: a malformed url http://example.i2p (no trailing '/') fails cryptically
|
||||||
*/
|
*/
|
||||||
public class EepGet {
|
public class EepGet {
|
||||||
protected I2PAppContext _context;
|
protected final I2PAppContext _context;
|
||||||
protected Log _log;
|
protected final Log _log;
|
||||||
protected boolean _shouldProxy;
|
protected final boolean _shouldProxy;
|
||||||
private String _proxyHost;
|
private final String _proxyHost;
|
||||||
private int _proxyPort;
|
private final int _proxyPort;
|
||||||
protected int _numRetries;
|
protected final int _numRetries;
|
||||||
private long _minSize; // minimum and maximum acceptable response size, -1 signifies unlimited,
|
private final long _minSize; // minimum and maximum acceptable response size, -1 signifies unlimited,
|
||||||
private long _maxSize; // applied both against whole responses and chunks
|
private final long _maxSize; // applied both against whole responses and chunks
|
||||||
protected String _outputFile;
|
protected final String _outputFile;
|
||||||
protected OutputStream _outputStream;
|
protected final OutputStream _outputStream;
|
||||||
/** url we were asked to fetch */
|
/** url we were asked to fetch */
|
||||||
protected String _url;
|
protected final String _url;
|
||||||
/** the URL we actually fetch from (may differ from the _url in case of redirect) */
|
/** the URL we actually fetch from (may differ from the _url in case of redirect) */
|
||||||
protected String _actualURL;
|
protected String _actualURL;
|
||||||
private String _postData;
|
private final String _postData;
|
||||||
private boolean _allowCaching;
|
private boolean _allowCaching;
|
||||||
protected final List<StatusListener> _listeners;
|
protected final List<StatusListener> _listeners;
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ public class EepGet {
|
|||||||
String outputFile, OutputStream outputStream, String url, boolean allowCaching,
|
String outputFile, OutputStream outputStream, String url, boolean allowCaching,
|
||||||
String etag, String lastModified, String postData) {
|
String etag, String lastModified, String postData) {
|
||||||
_context = ctx;
|
_context = ctx;
|
||||||
_log = ctx.logManager().getLog(EepGet.class);
|
_log = ctx.logManager().getLog(getClass());
|
||||||
_shouldProxy = (proxyHost != null) && (proxyHost.length() > 0) && (proxyPort > 0) && shouldProxy;
|
_shouldProxy = (proxyHost != null) && (proxyHost.length() > 0) && (proxyPort > 0) && shouldProxy;
|
||||||
_proxyHost = proxyHost;
|
_proxyHost = proxyHost;
|
||||||
_proxyPort = proxyPort;
|
_proxyPort = proxyPort;
|
||||||
@ -118,13 +118,7 @@ public class EepGet {
|
|||||||
_url = url;
|
_url = url;
|
||||||
_actualURL = url;
|
_actualURL = url;
|
||||||
_postData = postData;
|
_postData = postData;
|
||||||
_alreadyTransferred = 0;
|
|
||||||
_bytesTransferred = 0;
|
|
||||||
_bytesRemaining = -1;
|
_bytesRemaining = -1;
|
||||||
_currentAttempt = 0;
|
|
||||||
_transferFailed = false;
|
|
||||||
_headersRead = false;
|
|
||||||
_aborted = false;
|
|
||||||
_fetchHeaderTimeout = CONNECT_TIMEOUT;
|
_fetchHeaderTimeout = CONNECT_TIMEOUT;
|
||||||
_listeners = new ArrayList(1);
|
_listeners = new ArrayList(1);
|
||||||
_etag = etag;
|
_etag = etag;
|
||||||
@ -255,9 +249,9 @@ public class EepGet {
|
|||||||
public void attempting(String url);
|
public void attempting(String url);
|
||||||
}
|
}
|
||||||
protected class CLIStatusListener implements StatusListener {
|
protected class CLIStatusListener implements StatusListener {
|
||||||
private int _markSize;
|
private final int _markSize;
|
||||||
private int _lineSize;
|
private final int _lineSize;
|
||||||
private long _startedOn;
|
private final long _startedOn;
|
||||||
private long _written;
|
private long _written;
|
||||||
private long _previousWritten;
|
private long _previousWritten;
|
||||||
private long _discarded;
|
private long _discarded;
|
||||||
@ -271,9 +265,6 @@ public class EepGet {
|
|||||||
public CLIStatusListener(int markSize, int lineSize) {
|
public CLIStatusListener(int markSize, int lineSize) {
|
||||||
_markSize = markSize;
|
_markSize = markSize;
|
||||||
_lineSize = lineSize;
|
_lineSize = lineSize;
|
||||||
_written = 0;
|
|
||||||
_previousWritten = 0;
|
|
||||||
_discarded = 0;
|
|
||||||
_lastComplete = _context.clock().now();
|
_lastComplete = _context.clock().now();
|
||||||
_startedOn = _lastComplete;
|
_startedOn = _lastComplete;
|
||||||
_firstTime = true;
|
_firstTime = true;
|
||||||
|
@ -24,7 +24,7 @@ public class RouterClock extends Clock {
|
|||||||
* All of this is @since 0.7.12
|
* All of this is @since 0.7.12
|
||||||
*/
|
*/
|
||||||
private static final long MAX_SLEW = 50;
|
private static final long MAX_SLEW = 50;
|
||||||
private static final int DEFAULT_STRATUM = 8;
|
public static final int DEFAULT_STRATUM = 8;
|
||||||
private static final int WORST_STRATUM = 16;
|
private static final int WORST_STRATUM = 16;
|
||||||
/** the max NTP Timestamper delay is 30m right now, make this longer than that */
|
/** the max NTP Timestamper delay is 30m right now, make this longer than that */
|
||||||
private static final long MIN_DELAY_FOR_WORSE_STRATUM = 45*60*1000;
|
private static final long MIN_DELAY_FOR_WORSE_STRATUM = 45*60*1000;
|
||||||
@ -44,20 +44,27 @@ public class RouterClock extends Clock {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify how far away from the "correct" time the computer is - a positive
|
* Specify how far away from the "correct" time the computer is - a positive
|
||||||
* value means that we are slow, while a negative value means we are fast.
|
* value means that the system time is slow, while a negative value means the system time is fast.
|
||||||
*
|
*
|
||||||
|
* @param offsetMs the delta from System.currentTimeMillis() (NOT the delta from now())
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setOffset(long offsetMs, boolean force) {
|
public void setOffset(long offsetMs, boolean force) {
|
||||||
setOffset(offsetMs, force, DEFAULT_STRATUM);
|
setOffset(offsetMs, force, DEFAULT_STRATUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 0.7.12 */
|
/**
|
||||||
|
* @since 0.7.12
|
||||||
|
* @param offsetMs the delta from System.currentTimeMillis() (NOT the delta from now())
|
||||||
|
*/
|
||||||
private void setOffset(long offsetMs, int stratum) {
|
private void setOffset(long offsetMs, int stratum) {
|
||||||
setOffset(offsetMs, false, stratum);
|
setOffset(offsetMs, false, stratum);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 0.7.12 */
|
/**
|
||||||
|
* @since 0.7.12
|
||||||
|
* @param offsetMs the delta from System.currentTimeMillis() (NOT the delta from now())
|
||||||
|
*/
|
||||||
private void setOffset(long offsetMs, boolean force, int stratum) {
|
private void setOffset(long offsetMs, boolean force, int stratum) {
|
||||||
long delta = offsetMs - _offset;
|
long delta = offsetMs - _offset;
|
||||||
if (!force) {
|
if (!force) {
|
||||||
@ -91,7 +98,7 @@ public class RouterClock extends Clock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If so configured, check sanity of proposed clock offset
|
// If so configured, check sanity of proposed clock offset
|
||||||
if (Boolean.valueOf(_contextRC.getProperty("router.clockOffsetSanityCheck","true")).booleanValue() &&
|
if (_contextRC.getBooleanPropertyDefaultTrue("router.clockOffsetSanityCheck") &&
|
||||||
_alreadyChanged) {
|
_alreadyChanged) {
|
||||||
|
|
||||||
// Try calculating peer clock skew
|
// Try calculating peer clock skew
|
||||||
@ -192,6 +199,7 @@ public class RouterClock extends Clock {
|
|||||||
/*
|
/*
|
||||||
* How far we still have to slew, for diagnostics
|
* How far we still have to slew, for diagnostics
|
||||||
* @since 0.7.12
|
* @since 0.7.12
|
||||||
|
* @deprecated for debugging only
|
||||||
*/
|
*/
|
||||||
public long getDeltaOffset() {
|
public long getDeltaOffset() {
|
||||||
return _desiredOffset - _offset;
|
return _desiredOffset - _offset;
|
||||||
|
@ -14,7 +14,10 @@ import java.util.Set;
|
|||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.data.DataHelper;
|
||||||
|
import net.i2p.router.RouterClock;
|
||||||
import net.i2p.router.RouterContext;
|
import net.i2p.router.RouterContext;
|
||||||
|
import net.i2p.router.util.RFC822Date;
|
||||||
import net.i2p.util.EepGet;
|
import net.i2p.util.EepGet;
|
||||||
import net.i2p.util.I2PAppThread;
|
import net.i2p.util.I2PAppThread;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
@ -34,6 +37,7 @@ import net.i2p.util.Translate;
|
|||||||
* the router log, and the wrapper log.
|
* the router log, and the wrapper log.
|
||||||
*/
|
*/
|
||||||
public class Reseeder {
|
public class Reseeder {
|
||||||
|
/** FIXME don't keep a static reference, store _isRunning some other way */
|
||||||
private static ReseedRunner _reseedRunner;
|
private static ReseedRunner _reseedRunner;
|
||||||
private final RouterContext _context;
|
private final RouterContext _context;
|
||||||
private final Log _log;
|
private final Log _log;
|
||||||
@ -46,6 +50,10 @@ public class Reseeder {
|
|||||||
/**
|
/**
|
||||||
* NOTE - URLs in both the standard and SSL groups should use the same hostname and path,
|
* NOTE - URLs in both the standard and SSL groups should use the same hostname and path,
|
||||||
* so the reseed process will not download from both.
|
* so the reseed process will not download from both.
|
||||||
|
*
|
||||||
|
* NOTE - Each seedURL must be a directory, it must end with a '/',
|
||||||
|
* it can't end with 'index.html', for example. Both because of how individual file
|
||||||
|
* URLs are constructed, and because SSLEepGet doesn't follow redirects.
|
||||||
*/
|
*/
|
||||||
public static final String DEFAULT_SEED_URL =
|
public static final String DEFAULT_SEED_URL =
|
||||||
"http://a.netdb.i2p2.de/,http://c.netdb.i2p2.de/," +
|
"http://a.netdb.i2p2.de/,http://c.netdb.i2p2.de/," +
|
||||||
@ -98,13 +106,13 @@ public class Reseeder {
|
|||||||
private String _proxyHost;
|
private String _proxyHost;
|
||||||
private int _proxyPort;
|
private int _proxyPort;
|
||||||
private SSLEepGet.SSLState _sslState;
|
private SSLEepGet.SSLState _sslState;
|
||||||
|
private int _gotDate;
|
||||||
|
private long _attemptStarted;
|
||||||
|
private static final int MAX_DATE_SETS = 2;
|
||||||
|
|
||||||
public ReseedRunner() {
|
public ReseedRunner() {
|
||||||
_isRunning = false;
|
|
||||||
System.clearProperty(PROP_ERROR);
|
|
||||||
System.setProperty(PROP_STATUS, _("Reseeding"));
|
|
||||||
System.setProperty(PROP_INPROGRESS, "true");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRunning() { return _isRunning; }
|
public boolean isRunning() { return _isRunning; }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -113,6 +121,11 @@ public class Reseeder {
|
|||||||
*/
|
*/
|
||||||
public void run() {
|
public void run() {
|
||||||
_isRunning = true;
|
_isRunning = true;
|
||||||
|
System.clearProperty(PROP_ERROR);
|
||||||
|
System.setProperty(PROP_STATUS, _("Reseeding"));
|
||||||
|
System.setProperty(PROP_INPROGRESS, "true");
|
||||||
|
_attemptStarted = 0;
|
||||||
|
_gotDate = 0;
|
||||||
_sslState = null; // start fresh
|
_sslState = null; // start fresh
|
||||||
if (_context.getBooleanProperty(PROP_PROXY_ENABLE)) {
|
if (_context.getBooleanProperty(PROP_PROXY_ENABLE)) {
|
||||||
_proxyHost = _context.getProperty(PROP_PROXY_HOST);
|
_proxyHost = _context.getProperty(PROP_PROXY_HOST);
|
||||||
@ -152,8 +165,48 @@ public class Reseeder {
|
|||||||
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {}
|
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {}
|
||||||
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {}
|
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {}
|
||||||
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {}
|
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {}
|
||||||
public void headerReceived(String url, int attemptNum, String key, String val) {}
|
|
||||||
public void attempting(String url) {}
|
/**
|
||||||
|
* Use the Date header as a backup time source
|
||||||
|
*/
|
||||||
|
public void headerReceived(String url, int attemptNum, String key, String val) {
|
||||||
|
// We do this more than once, because
|
||||||
|
// the first SSL handshake may take a while, and it may take the server
|
||||||
|
// a while to render the index page.
|
||||||
|
if (_gotDate < MAX_DATE_SETS && "date".equalsIgnoreCase(key) && _attemptStarted > 0) {
|
||||||
|
long timeRcvd = System.currentTimeMillis();
|
||||||
|
long serverTime = RFC822Date.parse822Date(val);
|
||||||
|
if (serverTime > 0) {
|
||||||
|
// add 500ms since it's 1-sec resolution, and add half the RTT
|
||||||
|
long now = serverTime + 500 + ((timeRcvd - _attemptStarted) / 2);
|
||||||
|
long offset = now - _context.clock().now();
|
||||||
|
if (_context.clock().getUpdatedSuccessfully()) {
|
||||||
|
// 2nd time better than the first
|
||||||
|
if (_gotDate > 0)
|
||||||
|
_context.clock().setNow(now, RouterClock.DEFAULT_STRATUM - 2);
|
||||||
|
else
|
||||||
|
_context.clock().setNow(now, RouterClock.DEFAULT_STRATUM - 1);
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn("Reseed adjusting clock by " +
|
||||||
|
DataHelper.formatDuration(Math.abs(offset)));
|
||||||
|
} else {
|
||||||
|
// No peers or NTP yet, this is probably better than the peer average will be for a while
|
||||||
|
// default stratum - 1, so the peer average is a worse stratum
|
||||||
|
_context.clock().setNow(now, RouterClock.DEFAULT_STRATUM - 1);
|
||||||
|
_log.logAlways(Log.WARN, "NTP failure, Reseed adjusting clock by " +
|
||||||
|
DataHelper.formatDuration(Math.abs(offset)));
|
||||||
|
}
|
||||||
|
_gotDate++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** save the start time */
|
||||||
|
public void attempting(String url) {
|
||||||
|
if (_gotDate < MAX_DATE_SETS)
|
||||||
|
_attemptStarted = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
// End of EepGet status listeners
|
// End of EepGet status listeners
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -235,7 +288,8 @@ public class Reseeder {
|
|||||||
**/
|
**/
|
||||||
private int reseedOne(String seedURL, boolean echoStatus) {
|
private int reseedOne(String seedURL, boolean echoStatus) {
|
||||||
try {
|
try {
|
||||||
final long timeLimit = _context.clock().now() + MAX_TIME_PER_HOST;
|
// Don't use context clock as we may be adjusting the time
|
||||||
|
final long timeLimit = System.currentTimeMillis() + MAX_TIME_PER_HOST;
|
||||||
System.setProperty(PROP_STATUS, _("Reseeding: fetching seed URL."));
|
System.setProperty(PROP_STATUS, _("Reseeding: fetching seed URL."));
|
||||||
System.err.println("Reseeding from " + seedURL);
|
System.err.println("Reseeding from " + seedURL);
|
||||||
URL dir = new URL(seedURL);
|
URL dir = new URL(seedURL);
|
||||||
@ -275,7 +329,7 @@ public class Reseeder {
|
|||||||
int errors = 0;
|
int errors = 0;
|
||||||
// 200 max from one URL
|
// 200 max from one URL
|
||||||
for (Iterator<String> iter = urlList.iterator();
|
for (Iterator<String> iter = urlList.iterator();
|
||||||
iter.hasNext() && fetched < 200 && _context.clock().now() < timeLimit; ) {
|
iter.hasNext() && fetched < 200 && System.currentTimeMillis() < timeLimit; ) {
|
||||||
try {
|
try {
|
||||||
System.setProperty(PROP_STATUS,
|
System.setProperty(PROP_STATUS,
|
||||||
_("Reseeding: fetching router info from seed URL ({0} successful, {1} errors).", fetched, errors));
|
_("Reseeding: fetching router info from seed URL ({0} successful, {1} errors).", fetched, errors));
|
||||||
|
@ -509,7 +509,7 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
|
|||||||
buf.append("<tt>");
|
buf.append("<tt>");
|
||||||
boolean found = _context.netDb().lookupRouterInfoLocally(peer) != null;
|
boolean found = _context.netDb().lookupRouterInfoLocally(peer) != null;
|
||||||
if (found)
|
if (found)
|
||||||
buf.append("<a title=\"").append(_("NetDb entry")).append("\" href=\"netdb.jsp?r=").append(h).append("\">");
|
buf.append("<a title=\"").append(_("NetDb entry")).append("\" href=\"netdb?r=").append(h).append("\">");
|
||||||
buf.append(h);
|
buf.append(h);
|
||||||
if (found)
|
if (found)
|
||||||
buf.append("</a>");
|
buf.append("</a>");
|
||||||
|
@ -399,7 +399,7 @@ class EstablishState {
|
|||||||
_context.clock().setOffset(1000 * (_tsB - _tsA), true);
|
_context.clock().setOffset(1000 * (_tsB - _tsA), true);
|
||||||
_tsA = _tsB;
|
_tsA = _tsB;
|
||||||
if (diff != 0)
|
if (diff != 0)
|
||||||
_log.error("NTP failure, NTCP adjusting clock by " + DataHelper.formatDuration(diff));
|
_log.logAlways(Log.WARN, "NTP failure, NTCP adjusting clock by " + DataHelper.formatDuration(diff));
|
||||||
} else if (diff >= Router.CLOCK_FUDGE_FACTOR) {
|
} else if (diff >= Router.CLOCK_FUDGE_FACTOR) {
|
||||||
_context.statManager().addRateData("ntcp.invalidOutboundSkew", diff, 0);
|
_context.statManager().addRateData("ntcp.invalidOutboundSkew", diff, 0);
|
||||||
_transport.markReachable(_con.getRemotePeer().calculateHash(), false);
|
_transport.markReachable(_con.getRemotePeer().calculateHash(), false);
|
||||||
@ -617,7 +617,7 @@ class EstablishState {
|
|||||||
_context.clock().setOffset(1000 * (_tsB - tsA), true);
|
_context.clock().setOffset(1000 * (_tsB - tsA), true);
|
||||||
tsA = _tsB;
|
tsA = _tsB;
|
||||||
if (diff != 0)
|
if (diff != 0)
|
||||||
_log.error("NTP failure, NTCP adjusting clock by " + DataHelper.formatDuration(diff));
|
_log.logAlways(Log.WARN, "NTP failure, NTCP adjusting clock by " + DataHelper.formatDuration(diff));
|
||||||
} else if (diff >= Router.CLOCK_FUDGE_FACTOR) {
|
} else if (diff >= Router.CLOCK_FUDGE_FACTOR) {
|
||||||
_context.statManager().addRateData("ntcp.invalidInboundSkew", diff, 0);
|
_context.statManager().addRateData("ntcp.invalidInboundSkew", diff, 0);
|
||||||
_transport.markReachable(alice.calculateHash(), true);
|
_transport.markReachable(alice.calculateHash(), true);
|
||||||
|
@ -473,7 +473,7 @@ class PacketHandler {
|
|||||||
// so we have to wait for NTCP to do it
|
// so we have to wait for NTCP to do it
|
||||||
_context.clock().setOffset(0 - skew, true);
|
_context.clock().setOffset(0 - skew, true);
|
||||||
if (skew != 0)
|
if (skew != 0)
|
||||||
_log.error("NTP failure, UDP adjusting clock by " + DataHelper.formatDuration(Math.abs(skew)));
|
_log.logAlways(Log.WARN, "NTP failure, UDP adjusting clock by " + DataHelper.formatDuration(Math.abs(skew)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skew > GRACE_PERIOD) {
|
if (skew > GRACE_PERIOD) {
|
||||||
|
51
router/java/src/net/i2p/router/util/RFC822Date.java
Normal file
51
router/java/src/net/i2p/router/util/RFC822Date.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package net.i2p.router.util;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moved from NewsFetcher
|
||||||
|
* @since 0.8.5
|
||||||
|
*/
|
||||||
|
public abstract class RFC822Date {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http://jimyjoshi.com/blog/2007/08/rfc822dateparsinginjava.html
|
||||||
|
* Apparently public domain
|
||||||
|
* Probably don't need all of these...
|
||||||
|
*/
|
||||||
|
private static final SimpleDateFormat rfc822DateFormats[] = new SimpleDateFormat[] {
|
||||||
|
new SimpleDateFormat("EEE, d MMM yy HH:mm:ss z", Locale.US),
|
||||||
|
new SimpleDateFormat("EEE, d MMM yy HH:mm z", Locale.US),
|
||||||
|
new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z", Locale.US),
|
||||||
|
new SimpleDateFormat("EEE, d MMM yyyy HH:mm z", Locale.US),
|
||||||
|
new SimpleDateFormat("d MMM yy HH:mm z", Locale.US),
|
||||||
|
new SimpleDateFormat("d MMM yy HH:mm:ss z", Locale.US),
|
||||||
|
new SimpleDateFormat("d MMM yyyy HH:mm z", Locale.US),
|
||||||
|
new SimpleDateFormat("d MMM yyyy HH:mm:ss z", Locale.US)
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* new Date(String foo) is deprecated, so let's do this the hard way
|
||||||
|
*
|
||||||
|
* @param s non-null
|
||||||
|
* @return -1 on failure
|
||||||
|
*/
|
||||||
|
public static long parse822Date(String s) {
|
||||||
|
for (int i = 0; i < rfc822DateFormats.length; i++) {
|
||||||
|
try {
|
||||||
|
Date date = rfc822DateFormats[i].parse(s);
|
||||||
|
if (date != null)
|
||||||
|
return date.getTime();
|
||||||
|
} catch (ParseException pe) {}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.8.2 */
|
||||||
|
public static String to822Date(long t) {
|
||||||
|
return (new SimpleDateFormat("d MMM yyyy HH:mm:ss z", Locale.US)).format(new Date(t));
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user