forked from I2P_Developers/i2p.i2p
Router timestamper:
- Add country-to-continent mapping - Add continent pool.ntp.org zones as first fallback, this will improve time service for countries that don't have a zone - Don't start threads in constructors - Fix logging, better prevention of initialization loops - Log severe errors to wrapper log also continent.txt file from http://dev.maxmind.com/geoip/legacy/codes/country_continent/ Creative Commons Attribution-ShareAlike 3.0 Unported License http://dev.maxmind.com/geoip/legacy/geolite/ Terms already met in LICENSE.txt
This commit is contained in:
@ -1405,6 +1405,7 @@
|
|||||||
<copy file="installer/resources/countries.txt" todir="pkg-temp/geoip/" />
|
<copy file="installer/resources/countries.txt" todir="pkg-temp/geoip/" />
|
||||||
<!-- small enough to include for now -->
|
<!-- small enough to include for now -->
|
||||||
<copy file="installer/resources/geoipv6.dat.gz" todir="pkg-temp/geoip/" />
|
<copy file="installer/resources/geoipv6.dat.gz" todir="pkg-temp/geoip/" />
|
||||||
|
<copy file="installer/resources/continents.txt" todir="pkg-temp/geoip/" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="prepupdateRouter" depends="buildrouter, deletepkg-temp">
|
<target name="prepupdateRouter" depends="buildrouter, deletepkg-temp">
|
||||||
@ -1422,6 +1423,7 @@
|
|||||||
<copy file="installer/resources/geoip.txt" todir="pkg-temp/geoip/" />
|
<copy file="installer/resources/geoip.txt" todir="pkg-temp/geoip/" />
|
||||||
<copy file="installer/resources/geoipv6.dat.gz" todir="pkg-temp/geoip/" />
|
<copy file="installer/resources/geoipv6.dat.gz" todir="pkg-temp/geoip/" />
|
||||||
<copy file="installer/resources/countries.txt" todir="pkg-temp/geoip/" />
|
<copy file="installer/resources/countries.txt" todir="pkg-temp/geoip/" />
|
||||||
|
<copy file="installer/resources/continents.txt" todir="pkg-temp/geoip/" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- All jetty jars required for update.
|
<!-- All jetty jars required for update.
|
||||||
|
255
installer/resources/continents.txt
Normal file
255
installer/resources/continents.txt
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
# From http://dev.maxmind.com/static/csv/codes/country_continent.csv
|
||||||
|
# Fetched 2015-04-21
|
||||||
|
#"iso 3166 country","continent code"
|
||||||
|
A1,--
|
||||||
|
A2,--
|
||||||
|
AD,EU
|
||||||
|
AE,AS
|
||||||
|
AF,AS
|
||||||
|
AG,NA
|
||||||
|
AI,NA
|
||||||
|
AL,EU
|
||||||
|
AM,AS
|
||||||
|
AN,NA
|
||||||
|
AO,AF
|
||||||
|
AP,AS
|
||||||
|
AQ,AN
|
||||||
|
AR,SA
|
||||||
|
AS,OC
|
||||||
|
AT,EU
|
||||||
|
AU,OC
|
||||||
|
AW,NA
|
||||||
|
AX,EU
|
||||||
|
AZ,AS
|
||||||
|
BA,EU
|
||||||
|
BB,NA
|
||||||
|
BD,AS
|
||||||
|
BE,EU
|
||||||
|
BF,AF
|
||||||
|
BG,EU
|
||||||
|
BH,AS
|
||||||
|
BI,AF
|
||||||
|
BJ,AF
|
||||||
|
BL,NA
|
||||||
|
BM,NA
|
||||||
|
BN,AS
|
||||||
|
BO,SA
|
||||||
|
BR,SA
|
||||||
|
BS,NA
|
||||||
|
BT,AS
|
||||||
|
BV,AN
|
||||||
|
BW,AF
|
||||||
|
BY,EU
|
||||||
|
BZ,NA
|
||||||
|
CA,NA
|
||||||
|
CC,AS
|
||||||
|
CD,AF
|
||||||
|
CF,AF
|
||||||
|
CG,AF
|
||||||
|
CH,EU
|
||||||
|
CI,AF
|
||||||
|
CK,OC
|
||||||
|
CL,SA
|
||||||
|
CM,AF
|
||||||
|
CN,AS
|
||||||
|
CO,SA
|
||||||
|
CR,NA
|
||||||
|
CU,NA
|
||||||
|
CV,AF
|
||||||
|
CX,AS
|
||||||
|
CY,AS
|
||||||
|
CZ,EU
|
||||||
|
DE,EU
|
||||||
|
DJ,AF
|
||||||
|
DK,EU
|
||||||
|
DM,NA
|
||||||
|
DO,NA
|
||||||
|
DZ,AF
|
||||||
|
EC,SA
|
||||||
|
EE,EU
|
||||||
|
EG,AF
|
||||||
|
EH,AF
|
||||||
|
ER,AF
|
||||||
|
ES,EU
|
||||||
|
ET,AF
|
||||||
|
EU,EU
|
||||||
|
FI,EU
|
||||||
|
FJ,OC
|
||||||
|
FK,SA
|
||||||
|
FM,OC
|
||||||
|
FO,EU
|
||||||
|
FR,EU
|
||||||
|
FX,EU
|
||||||
|
GA,AF
|
||||||
|
GB,EU
|
||||||
|
GD,NA
|
||||||
|
GE,AS
|
||||||
|
GF,SA
|
||||||
|
GG,EU
|
||||||
|
GH,AF
|
||||||
|
GI,EU
|
||||||
|
GL,NA
|
||||||
|
GM,AF
|
||||||
|
GN,AF
|
||||||
|
GP,NA
|
||||||
|
GQ,AF
|
||||||
|
GR,EU
|
||||||
|
GS,AN
|
||||||
|
GT,NA
|
||||||
|
GU,OC
|
||||||
|
GW,AF
|
||||||
|
GY,SA
|
||||||
|
HK,AS
|
||||||
|
HM,AN
|
||||||
|
HN,NA
|
||||||
|
HR,EU
|
||||||
|
HT,NA
|
||||||
|
HU,EU
|
||||||
|
ID,AS
|
||||||
|
IE,EU
|
||||||
|
IL,AS
|
||||||
|
IM,EU
|
||||||
|
IN,AS
|
||||||
|
IO,AS
|
||||||
|
IQ,AS
|
||||||
|
IR,AS
|
||||||
|
IS,EU
|
||||||
|
IT,EU
|
||||||
|
JE,EU
|
||||||
|
JM,NA
|
||||||
|
JO,AS
|
||||||
|
JP,AS
|
||||||
|
KE,AF
|
||||||
|
KG,AS
|
||||||
|
KH,AS
|
||||||
|
KI,OC
|
||||||
|
KM,AF
|
||||||
|
KN,NA
|
||||||
|
KP,AS
|
||||||
|
KR,AS
|
||||||
|
KW,AS
|
||||||
|
KY,NA
|
||||||
|
KZ,AS
|
||||||
|
LA,AS
|
||||||
|
LB,AS
|
||||||
|
LC,NA
|
||||||
|
LI,EU
|
||||||
|
LK,AS
|
||||||
|
LR,AF
|
||||||
|
LS,AF
|
||||||
|
LT,EU
|
||||||
|
LU,EU
|
||||||
|
LV,EU
|
||||||
|
LY,AF
|
||||||
|
MA,AF
|
||||||
|
MC,EU
|
||||||
|
MD,EU
|
||||||
|
ME,EU
|
||||||
|
MF,NA
|
||||||
|
MG,AF
|
||||||
|
MH,OC
|
||||||
|
MK,EU
|
||||||
|
ML,AF
|
||||||
|
MM,AS
|
||||||
|
MN,AS
|
||||||
|
MO,AS
|
||||||
|
MP,OC
|
||||||
|
MQ,NA
|
||||||
|
MR,AF
|
||||||
|
MS,NA
|
||||||
|
MT,EU
|
||||||
|
MU,AF
|
||||||
|
MV,AS
|
||||||
|
MW,AF
|
||||||
|
MX,NA
|
||||||
|
MY,AS
|
||||||
|
MZ,AF
|
||||||
|
NA,AF
|
||||||
|
NC,OC
|
||||||
|
NE,AF
|
||||||
|
NF,OC
|
||||||
|
NG,AF
|
||||||
|
NI,NA
|
||||||
|
NL,EU
|
||||||
|
NO,EU
|
||||||
|
NP,AS
|
||||||
|
NR,OC
|
||||||
|
NU,OC
|
||||||
|
NZ,OC
|
||||||
|
O1,--
|
||||||
|
OM,AS
|
||||||
|
PA,NA
|
||||||
|
PE,SA
|
||||||
|
PF,OC
|
||||||
|
PG,OC
|
||||||
|
PH,AS
|
||||||
|
PK,AS
|
||||||
|
PL,EU
|
||||||
|
PM,NA
|
||||||
|
PN,OC
|
||||||
|
PR,NA
|
||||||
|
PS,AS
|
||||||
|
PT,EU
|
||||||
|
PW,OC
|
||||||
|
PY,SA
|
||||||
|
QA,AS
|
||||||
|
RE,AF
|
||||||
|
RO,EU
|
||||||
|
RS,EU
|
||||||
|
RU,EU
|
||||||
|
RW,AF
|
||||||
|
SA,AS
|
||||||
|
SB,OC
|
||||||
|
SC,AF
|
||||||
|
SD,AF
|
||||||
|
SE,EU
|
||||||
|
SG,AS
|
||||||
|
SH,AF
|
||||||
|
SI,EU
|
||||||
|
SJ,EU
|
||||||
|
SK,EU
|
||||||
|
SL,AF
|
||||||
|
SM,EU
|
||||||
|
SN,AF
|
||||||
|
SO,AF
|
||||||
|
SR,SA
|
||||||
|
ST,AF
|
||||||
|
SV,NA
|
||||||
|
SY,AS
|
||||||
|
SZ,AF
|
||||||
|
TC,NA
|
||||||
|
TD,AF
|
||||||
|
TF,AN
|
||||||
|
TG,AF
|
||||||
|
TH,AS
|
||||||
|
TJ,AS
|
||||||
|
TK,OC
|
||||||
|
TL,AS
|
||||||
|
TM,AS
|
||||||
|
TN,AF
|
||||||
|
TO,OC
|
||||||
|
TR,EU
|
||||||
|
TT,NA
|
||||||
|
TV,OC
|
||||||
|
TW,AS
|
||||||
|
TZ,AF
|
||||||
|
UA,EU
|
||||||
|
UG,AF
|
||||||
|
UM,OC
|
||||||
|
US,NA
|
||||||
|
UY,SA
|
||||||
|
UZ,AS
|
||||||
|
VA,EU
|
||||||
|
VC,NA
|
||||||
|
VE,SA
|
||||||
|
VG,NA
|
||||||
|
VI,NA
|
||||||
|
VN,AS
|
||||||
|
VU,OC
|
||||||
|
WF,OC
|
||||||
|
WS,OC
|
||||||
|
YE,AS
|
||||||
|
YT,AF
|
||||||
|
ZA,AF
|
||||||
|
ZM,AF
|
||||||
|
ZW,AF
|
@ -40,7 +40,7 @@ public class RouterClock extends Clock {
|
|||||||
/** use system time for this */
|
/** use system time for this */
|
||||||
private long _lastChanged;
|
private long _lastChanged;
|
||||||
private int _lastStratum;
|
private int _lastStratum;
|
||||||
private final Timestamper _timeStamper;
|
private final RouterTimestamper _timeStamper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the system clock shifts by this much,
|
* If the system clock shifts by this much,
|
||||||
@ -53,6 +53,9 @@ public class RouterClock extends Clock {
|
|||||||
private final Set<ClockShiftListener> _shiftListeners;
|
private final Set<ClockShiftListener> _shiftListeners;
|
||||||
private volatile long _lastShiftNanos;
|
private volatile long _lastShiftNanos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does not start. Caller MUST call start()
|
||||||
|
*/
|
||||||
public RouterClock(RouterContext context) {
|
public RouterClock(RouterContext context) {
|
||||||
super(context);
|
super(context);
|
||||||
_lastStratum = WORST_STRATUM;
|
_lastStratum = WORST_STRATUM;
|
||||||
@ -62,6 +65,14 @@ public class RouterClock extends Clock {
|
|||||||
_timeStamper = new RouterTimestamper(context, this);
|
_timeStamper = new RouterTimestamper(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cannot be stopped, but RouterTimestamper registers a shutdown task.
|
||||||
|
* @since 0.9.20
|
||||||
|
*/
|
||||||
|
public void start() {
|
||||||
|
_timeStamper.startTimestamper();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The RouterTimestamper
|
* The RouterTimestamper
|
||||||
*/
|
*/
|
||||||
|
@ -483,8 +483,11 @@ public class RouterContext extends I2PAppContext {
|
|||||||
@Override
|
@Override
|
||||||
protected void initializeClock() {
|
protected void initializeClock() {
|
||||||
synchronized (_lock1) {
|
synchronized (_lock1) {
|
||||||
if (_clock == null)
|
if (_clock == null) {
|
||||||
_clock = new RouterClock(this);
|
RouterClock rc = new RouterClock(this);
|
||||||
|
rc.start();
|
||||||
|
_clock = rc;
|
||||||
|
}
|
||||||
_clockInitialized = true;
|
_clockInitialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,10 @@ import net.i2p.util.Log;
|
|||||||
*/
|
*/
|
||||||
public class RouterTimestamper extends Timestamper {
|
public class RouterTimestamper extends Timestamper {
|
||||||
private final I2PAppContext _context;
|
private final I2PAppContext _context;
|
||||||
|
// warning, may be null
|
||||||
private Log _log;
|
private Log _log;
|
||||||
private final List<String> _servers;
|
private final List<String> _servers;
|
||||||
private List<String> _priorityServers;
|
private List<List<String>> _priorityServers;
|
||||||
private final List<UpdateListener> _listeners;
|
private final List<UpdateListener> _listeners;
|
||||||
private int _queryFrequency;
|
private int _queryFrequency;
|
||||||
private int _concurringServers;
|
private int _concurringServers;
|
||||||
@ -33,11 +34,12 @@ public class RouterTimestamper extends Timestamper {
|
|||||||
private boolean _wellSynced;
|
private boolean _wellSynced;
|
||||||
private volatile boolean _isRunning;
|
private volatile boolean _isRunning;
|
||||||
private Thread _timestamperThread;
|
private Thread _timestamperThread;
|
||||||
|
private final Zones _zones;
|
||||||
|
|
||||||
private static final int MIN_QUERY_FREQUENCY = 5*60*1000;
|
private static final int MIN_QUERY_FREQUENCY = 5*60*1000;
|
||||||
private static final int DEFAULT_QUERY_FREQUENCY = 11*60*1000;
|
private static final int DEFAULT_QUERY_FREQUENCY = 11*60*1000;
|
||||||
private static final String DEFAULT_SERVER_LIST = "0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org";
|
private static final String DEFAULT_SERVER_LIST = "0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org";
|
||||||
private static final String DEFAULT_DISABLED = "true";
|
private static final boolean DEFAULT_DISABLED = true;
|
||||||
/** how many times do we have to query if we are changing the clock? */
|
/** how many times do we have to query if we are changing the clock? */
|
||||||
private static final int DEFAULT_CONCURRING_SERVERS = 3;
|
private static final int DEFAULT_CONCURRING_SERVERS = 3;
|
||||||
private static final int MAX_CONSECUTIVE_FAILS = 10;
|
private static final int MAX_CONSECUTIVE_FAILS = 10;
|
||||||
@ -51,13 +53,23 @@ public class RouterTimestamper extends Timestamper {
|
|||||||
/** if different SNTP servers differ by more than 10s, someone is b0rked */
|
/** if different SNTP servers differ by more than 10s, someone is b0rked */
|
||||||
private static final int MAX_VARIANCE = 10*1000;
|
private static final int MAX_VARIANCE = 10*1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does not start. Caller MUST call startTimestamper()
|
||||||
|
*/
|
||||||
public RouterTimestamper(I2PAppContext ctx) {
|
public RouterTimestamper(I2PAppContext ctx) {
|
||||||
this(ctx, null, true);
|
this(ctx, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does not start. Caller MUST call startTimestamper()
|
||||||
|
*/
|
||||||
public RouterTimestamper(I2PAppContext ctx, UpdateListener lsnr) {
|
public RouterTimestamper(I2PAppContext ctx, UpdateListener lsnr) {
|
||||||
this(ctx, lsnr, true);
|
this(ctx, lsnr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does not start. Caller MUST call startTimestamper()
|
||||||
|
*/
|
||||||
public RouterTimestamper(I2PAppContext ctx, UpdateListener lsnr, boolean daemon) {
|
public RouterTimestamper(I2PAppContext ctx, UpdateListener lsnr, boolean daemon) {
|
||||||
super();
|
super();
|
||||||
// moved here to prevent problems with synchronized statements.
|
// moved here to prevent problems with synchronized statements.
|
||||||
@ -71,15 +83,17 @@ public class RouterTimestamper extends Timestamper {
|
|||||||
// 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.
|
||||||
// We still need to be instantiated since the router calls clock().getTimestamper().waitForInitialization()
|
// We still need to be instantiated since the router calls clock().getTimestamper().waitForInitialization()
|
||||||
String disabled = ctx.getProperty(PROP_DISABLED, DEFAULT_DISABLED);
|
_disabled = ctx.getProperty(PROP_DISABLED, DEFAULT_DISABLED);
|
||||||
if (Boolean.parseBoolean(disabled)) {
|
if (_disabled) {
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
|
_zones = null;
|
||||||
|
System.out.println("Warning: NTP is disabled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (lsnr != null)
|
if (lsnr != null)
|
||||||
_listeners.add(lsnr);
|
_listeners.add(lsnr);
|
||||||
|
_zones = new Zones(ctx);
|
||||||
updateConfig();
|
updateConfig();
|
||||||
startTimestamper();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getServerCount() {
|
public int getServerCount() {
|
||||||
@ -110,7 +124,9 @@ public class RouterTimestamper extends Timestamper {
|
|||||||
return _listeners.get(index);
|
return _listeners.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startTimestamper() {
|
public void startTimestamper() {
|
||||||
|
if (_disabled || _initialized)
|
||||||
|
return;
|
||||||
_timestamperThread = new I2PThread(this, "Timestamper", _daemon);
|
_timestamperThread = new I2PThread(this, "Timestamper", _daemon);
|
||||||
_timestamperThread.setPriority(I2PThread.MIN_PRIORITY);
|
_timestamperThread.setPriority(I2PThread.MIN_PRIORITY);
|
||||||
_isRunning = true;
|
_isRunning = true;
|
||||||
@ -149,48 +165,72 @@ public class RouterTimestamper extends Timestamper {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try { Thread.sleep(1000); } catch (InterruptedException ie) {}
|
|
||||||
_log = _context.logManager().getLog(Timestamper.class);
|
|
||||||
if (_log.shouldLog(Log.INFO))
|
|
||||||
_log.info("Starting timestamper");
|
|
||||||
boolean lastFailed = false;
|
boolean lastFailed = false;
|
||||||
try {
|
try {
|
||||||
while (_isRunning) {
|
while (_isRunning) {
|
||||||
|
// NOTE: _log is null the first time through, to prevent problems and stack overflows
|
||||||
updateConfig();
|
updateConfig();
|
||||||
if (!_disabled) {
|
if (!_disabled) {
|
||||||
// first the servers for our country, if we know what country we're in...
|
// first the servers for our country and continent, we know what country we're in...
|
||||||
if (_priorityServers != null) {
|
if (_priorityServers != null) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
for (List<String> servers : _priorityServers) {
|
||||||
_log.debug("Querying servers " + _priorityServers);
|
if (_log != null && _log.shouldDebug())
|
||||||
try {
|
_log.debug("Querying servers " + servers);
|
||||||
lastFailed = !queryTime(_priorityServers.toArray(new String[_priorityServers.size()]));
|
try {
|
||||||
} catch (IllegalArgumentException iae) {
|
lastFailed = !queryTime(servers.toArray(new String[servers.size()]));
|
||||||
if ( (!lastFailed) && (_log.shouldLog(Log.WARN)) )
|
} catch (IllegalArgumentException iae) {
|
||||||
_log.warn("Unable to reach country-specific NTP servers");
|
if (!lastFailed && _log != null && _log.shouldWarn())
|
||||||
lastFailed = true;
|
_log.warn("Unable to reach any regional NTP servers: " + servers);
|
||||||
|
lastFailed = true;
|
||||||
|
}
|
||||||
|
if (!lastFailed)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ... and then the global list, if that failed
|
// ... and then the global list, if that failed
|
||||||
if (_priorityServers == null || lastFailed) {
|
if (_priorityServers == null || lastFailed) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log != null && _log.shouldDebug())
|
||||||
_log.debug("Querying servers " + _servers);
|
_log.debug("Querying servers " + _servers);
|
||||||
try {
|
try {
|
||||||
lastFailed = !queryTime(_servers.toArray(new String[_servers.size()]));
|
lastFailed = !queryTime(_servers.toArray(new String[_servers.size()]));
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
if ( (!_initialized) && (_log.shouldLog(Log.ERROR)) ) {
|
|
||||||
List<String> all = new ArrayList<String>();
|
|
||||||
if (_priorityServers != null)
|
|
||||||
all.addAll(_priorityServers);
|
|
||||||
all.addAll(_servers);
|
|
||||||
_log.error("Unable to reach any of the NTP servers " + all + " - network disconnected? Or set time.sntpServerList=myserver1.com,myserver2.com in advanced configuration.");
|
|
||||||
}
|
|
||||||
lastFailed = true;
|
lastFailed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_initialized = true;
|
boolean wasInitialized = _initialized;
|
||||||
|
if (!wasInitialized)
|
||||||
|
_initialized = true;
|
||||||
synchronized (this) { notifyAll(); }
|
synchronized (this) { notifyAll(); }
|
||||||
|
if (!wasInitialized) {
|
||||||
|
// let the log manager get initialized
|
||||||
|
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
|
||||||
|
// NOW we set up logging
|
||||||
|
_log = _context.logManager().getLog(RouterTimestamper.class);
|
||||||
|
if (lastFailed) {
|
||||||
|
List<String> all = new ArrayList<String>(9);
|
||||||
|
if (_priorityServers != null) {
|
||||||
|
for (List<String> servers : _priorityServers) {
|
||||||
|
all.addAll(servers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
all.addAll(_servers);
|
||||||
|
String msg = "Unable to reach any of the NTP servers " + all +
|
||||||
|
" - network disconnected? Or set time.sntpServerList=myserver1.com,myserver2.com in advanced configuration.";
|
||||||
|
_log.logAlways(Log.WARN, msg);
|
||||||
|
System.out.println("Warning: " + msg);
|
||||||
|
} else if (_log.shouldDebug()) {
|
||||||
|
_log.debug("NTP initialization successful");
|
||||||
|
int i = 1;
|
||||||
|
if (_priorityServers != null) {
|
||||||
|
for (List<String> servers : _priorityServers) {
|
||||||
|
_log.debug("NTP Server list " + (i++) + ": " + servers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_log.debug("NTP Server list " + i + ": " + _servers);
|
||||||
|
}
|
||||||
|
}
|
||||||
long sleepTime;
|
long sleepTime;
|
||||||
if (lastFailed) {
|
if (lastFailed) {
|
||||||
if (++_consecutiveFails >= MAX_CONSECUTIVE_FAILS)
|
if (++_consecutiveFails >= MAX_CONSECUTIVE_FAILS)
|
||||||
@ -206,8 +246,10 @@ public class RouterTimestamper extends Timestamper {
|
|||||||
try { Thread.sleep(sleepTime); } catch (InterruptedException ie) {}
|
try { Thread.sleep(sleepTime); } catch (InterruptedException ie) {}
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
_log.log(Log.CRIT, "Timestamper died!", t);
|
|
||||||
synchronized (this) { notifyAll(); }
|
synchronized (this) { notifyAll(); }
|
||||||
|
if (_log != null)
|
||||||
|
_log.log(Log.CRIT, "Timestamper died!", t);
|
||||||
|
t.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +274,7 @@ public class RouterTimestamper extends Timestamper {
|
|||||||
found[i] = delta;
|
found[i] = delta;
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
if (Math.abs(delta) < MAX_VARIANCE) {
|
if (Math.abs(delta) < MAX_VARIANCE) {
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log != null && _log.shouldInfo())
|
||||||
_log.info("a single SNTP query was within the tolerance (" + delta + "ms)");
|
_log.info("a single SNTP query was within the tolerance (" + delta + "ms)");
|
||||||
// If less than a half second on the first try, we're in good shape
|
// If less than a half second on the first try, we're in good shape
|
||||||
_wellSynced = Math.abs(delta) < 500;
|
_wellSynced = Math.abs(delta) < 500;
|
||||||
@ -243,7 +285,7 @@ public class RouterTimestamper extends Timestamper {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Math.abs(delta - expectedDelta) > MAX_VARIANCE) {
|
if (Math.abs(delta - expectedDelta) > MAX_VARIANCE) {
|
||||||
if (_log.shouldLog(Log.ERROR)) {
|
if (_log != null && _log.shouldError()) {
|
||||||
StringBuilder err = new StringBuilder(96);
|
StringBuilder err = new StringBuilder(96);
|
||||||
err.append("SNTP client variance exceeded at query ").append(i);
|
err.append("SNTP client variance exceeded at query ").append(i);
|
||||||
err.append(". expected = ");
|
err.append(". expected = ");
|
||||||
@ -260,7 +302,7 @@ public class RouterTimestamper extends Timestamper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
stampTime(now, stratum);
|
stampTime(now, stratum);
|
||||||
if (_log.shouldLog(Log.DEBUG)) {
|
if (_log != null && _log.shouldDebug()) {
|
||||||
StringBuilder buf = new StringBuilder(64);
|
StringBuilder buf = new StringBuilder(64);
|
||||||
buf.append("Deltas: ");
|
buf.append("Deltas: ");
|
||||||
for (int i = 0; i < found.length; i++)
|
for (int i = 0; i < found.length; i++)
|
||||||
@ -280,13 +322,13 @@ public class RouterTimestamper extends Timestamper {
|
|||||||
for (UpdateListener lsnr : _listeners) {
|
for (UpdateListener lsnr : _listeners) {
|
||||||
lsnr.setNow(now, stratum);
|
lsnr.setNow(now, stratum);
|
||||||
}
|
}
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log != null && _log.shouldDebug())
|
||||||
_log.debug("Stamped the time as " + now + " (delta=" + (now-before) + ")");
|
_log.debug("Stamped the time as " + now + " (delta=" + (now-before) + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reload all the config elements from the appContext
|
* Reload all the config elements from the appContext.
|
||||||
*
|
* No logging allowed here
|
||||||
*/
|
*/
|
||||||
private void updateConfig() {
|
private void updateConfig() {
|
||||||
String serverList = _context.getProperty(PROP_SERVER_LIST);
|
String serverList = _context.getProperty(PROP_SERVER_LIST);
|
||||||
@ -298,10 +340,22 @@ public class RouterTimestamper extends Timestamper {
|
|||||||
if (country != null)
|
if (country != null)
|
||||||
country = country.toLowerCase(Locale.US);
|
country = country.toLowerCase(Locale.US);
|
||||||
}
|
}
|
||||||
if (country != null && country.length() > 0) {
|
if (country != null && country.length() > 0 &&
|
||||||
_priorityServers = new ArrayList<String>(3);
|
!country.equals("a1") && !country.equals("a2")) {
|
||||||
for (int i = 0; i < 3; i++)
|
_priorityServers = new ArrayList<List<String>>(2);
|
||||||
_priorityServers.add(i + "." + country + ".pool.ntp.org");
|
List<String> p1 = new ArrayList<String>(3);
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
p1.add(i + "." + country + ".pool.ntp.org");
|
||||||
|
}
|
||||||
|
_priorityServers.add(p1);
|
||||||
|
String zone = _zones.getZone(country);
|
||||||
|
if (zone != null) {
|
||||||
|
List<String> p2 = new ArrayList<String>(3);
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
p2.add(i + "." + zone + ".pool.ntp.org");
|
||||||
|
}
|
||||||
|
_priorityServers.add(p2);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_priorityServers = null;
|
_priorityServers = null;
|
||||||
}
|
}
|
||||||
@ -320,8 +374,7 @@ public class RouterTimestamper extends Timestamper {
|
|||||||
_queryFrequency = Math.max(MIN_QUERY_FREQUENCY,
|
_queryFrequency = Math.max(MIN_QUERY_FREQUENCY,
|
||||||
_context.getProperty(PROP_QUERY_FREQUENCY, DEFAULT_QUERY_FREQUENCY));
|
_context.getProperty(PROP_QUERY_FREQUENCY, DEFAULT_QUERY_FREQUENCY));
|
||||||
|
|
||||||
String disabled = _context.getProperty(PROP_DISABLED, DEFAULT_DISABLED);
|
_disabled = _context.getProperty(PROP_DISABLED, DEFAULT_DISABLED);
|
||||||
_disabled = Boolean.parseBoolean(disabled);
|
|
||||||
|
|
||||||
_concurringServers = Math.min(4, Math.max(1,
|
_concurringServers = Math.min(4, Math.max(1,
|
||||||
_context.getProperty(PROP_CONCURRING_SERVERS, DEFAULT_CONCURRING_SERVERS)));
|
_context.getProperty(PROP_CONCURRING_SERVERS, DEFAULT_CONCURRING_SERVERS)));
|
||||||
|
135
router/java/src/net/i2p/router/time/Zones.java
Normal file
135
router/java/src/net/i2p/router/time/Zones.java
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
package net.i2p.router.time;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.router.transport.GeoIP;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Country to continent mapping for NTP.
|
||||||
|
* @since 0.9.20
|
||||||
|
*/
|
||||||
|
class Zones {
|
||||||
|
|
||||||
|
private final I2PAppContext _context;
|
||||||
|
// can't log here, called from RouterClock constructor, stack overflow
|
||||||
|
//private final Log _log;
|
||||||
|
|
||||||
|
// lower case country to NTP region
|
||||||
|
private final Map<String, String> _countryToZone;
|
||||||
|
// upper case continent to NTP region
|
||||||
|
private final Map<String, String> _continentToZone;
|
||||||
|
|
||||||
|
private static final String CONTINENT_FILE_DEFAULT = "continents.txt";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ref: http://dev.maxmind.com/geoip/legacy/codes/country_continent/
|
||||||
|
* ref: http://www.pool.ntp.org/zone/@
|
||||||
|
*/
|
||||||
|
private static final String[] ZONES = {
|
||||||
|
// not an NTP zone
|
||||||
|
//"--", "anonymous-proxy",
|
||||||
|
"AF", "africa",
|
||||||
|
// not an NTP zone
|
||||||
|
//"AN", "antarctica",
|
||||||
|
"AS", "asia",
|
||||||
|
"EU", "europe",
|
||||||
|
"NA", "north-america",
|
||||||
|
"OC", "oceania",
|
||||||
|
"SA", "south-america"
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads in the file in the constructor,
|
||||||
|
* so hold onto this.
|
||||||
|
*/
|
||||||
|
public Zones(I2PAppContext ctx) {
|
||||||
|
_context = ctx;
|
||||||
|
//_log = ctx.logManager().getLog(Zones.class);
|
||||||
|
_countryToZone = new HashMap<String, String>(256);
|
||||||
|
_continentToZone = new HashMap<String, String>(8);
|
||||||
|
for (int i = 0; i < ZONES.length; i += 2) {
|
||||||
|
_continentToZone.put(ZONES[i], ZONES[i+1]);
|
||||||
|
}
|
||||||
|
readContinentFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the NTP zone for a country
|
||||||
|
*
|
||||||
|
* @param country non-null, two letter code, case-independent
|
||||||
|
* @return lower-case NTP zone, e.g. "africa", or null
|
||||||
|
*/
|
||||||
|
public String getZone (String country) {
|
||||||
|
return _countryToZone.get(country.toLowerCase(Locale.US));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read in and parse the continent file.
|
||||||
|
* The file need not be sorted.
|
||||||
|
*
|
||||||
|
* Format:
|
||||||
|
* #comment (# must be in column 1)
|
||||||
|
* country code,continent code
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* US,NA
|
||||||
|
*
|
||||||
|
* Modified from GeoIP.readCountryFile()
|
||||||
|
* ref: http://dev.maxmind.com/geoip/legacy/codes/country_continent/
|
||||||
|
*/
|
||||||
|
private void readContinentFile() {
|
||||||
|
String geoDir = _context.getProperty(GeoIP.PROP_GEOIP_DIR, GeoIP.GEOIP_DIR_DEFAULT);
|
||||||
|
File geoFile = new File(geoDir);
|
||||||
|
if (!geoFile.isAbsolute())
|
||||||
|
geoFile = new File(_context.getBaseDir(), geoDir);
|
||||||
|
geoFile = new File(geoFile, CONTINENT_FILE_DEFAULT);
|
||||||
|
if (!geoFile.exists()) {
|
||||||
|
//if (_log.shouldWarn())
|
||||||
|
// _log.warn("Continent file not found: " + geoFile.getAbsolutePath());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BufferedReader br = null;
|
||||||
|
try {
|
||||||
|
br = new BufferedReader(new InputStreamReader(
|
||||||
|
new FileInputStream(geoFile), "UTF-8"));
|
||||||
|
String line = null;
|
||||||
|
while ((line = br.readLine()) != null) {
|
||||||
|
try {
|
||||||
|
if (line.charAt(0) == '#')
|
||||||
|
continue;
|
||||||
|
String[] s = line.split(",");
|
||||||
|
String ucContinent = s[1].toUpperCase(Locale.US).trim();
|
||||||
|
String zone = _continentToZone.get(ucContinent);
|
||||||
|
if (zone == null)
|
||||||
|
continue;
|
||||||
|
String lcCountry = s[0].toLowerCase(Locale.US).trim();
|
||||||
|
_countryToZone.put(lcCountry, zone);
|
||||||
|
//if (_log.shouldDebug())
|
||||||
|
// _log.debug("Country " + lcCountry + " is in " + zone);
|
||||||
|
} catch (IndexOutOfBoundsException ioobe) {}
|
||||||
|
}
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
System.out.println("Error reading the continent file " + geoFile.getAbsolutePath());
|
||||||
|
} finally {
|
||||||
|
if (br != null) try { br.close(); } catch (IOException ioe) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****
|
||||||
|
public static void main(String args[]) {
|
||||||
|
Zones z = new Zones(I2PAppContext.getGlobalContext());
|
||||||
|
String tests[] = {"us", "US", "nz", "fr", "vU", "br", "cn", "ao", "A1", "foo" };
|
||||||
|
for (int i = 0; i < tests.length; i++) {
|
||||||
|
System.out.println(tests[i] + " : " + z.getZone(tests[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
****/
|
||||||
|
}
|
@ -73,7 +73,7 @@ public class GeoIP {
|
|||||||
|
|
||||||
static final String PROP_GEOIP_ENABLED = "routerconsole.geoip.enable";
|
static final String PROP_GEOIP_ENABLED = "routerconsole.geoip.enable";
|
||||||
public static final String PROP_GEOIP_DIR = "geoip.dir";
|
public static final String PROP_GEOIP_DIR = "geoip.dir";
|
||||||
static final String GEOIP_DIR_DEFAULT = "geoip";
|
public static final String GEOIP_DIR_DEFAULT = "geoip";
|
||||||
static final String GEOIP_FILE_DEFAULT = "geoip.txt";
|
static final String GEOIP_FILE_DEFAULT = "geoip.txt";
|
||||||
static final String COUNTRY_FILE_DEFAULT = "countries.txt";
|
static final String COUNTRY_FILE_DEFAULT = "countries.txt";
|
||||||
public static final String PROP_IP_COUNTRY = "i2np.lastCountry";
|
public static final String PROP_IP_COUNTRY = "i2np.lastCountry";
|
||||||
|
Reference in New Issue
Block a user