forked from I2P_Developers/i2p.i2p
> Date: Fri, 13 Aug 2004 15:58:30 +1200 (NZST)
> Message-ID: <1776.202.37.75.101.1092369510.squirrel@202.37.75.101> > From: adam@adambuckley.net > To: jrandom@i2p.net > > [...] > > I hereby authorize my NtpClient.java and NtpMessage.java code to be > redistributed under the BSD license for the purpose of integration with > the I2P project, providing that I am credited as the original author of > the code. > > [...] w00t! adam++ code migrated into core/java/src/net/i2p/time, integrated with Clock, dropping that whole ugly pass-the-time-through-URL, and hence dropped support for :7655/setTime. New router.config properties to control the timestamper: time.sntpServerList=pool.ntp.org,pool.ntp.org,pool.ntp.org time.queryFrequencyMs=300000 time.disabled=false So, to disable, add time.disabled=true to your router.config. It is enabled by default. Default router.config and startup scripts updated accordingly (since timestamper.jar is now gone)
This commit is contained in:
@ -17,6 +17,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.time.Timestamper;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.ClientTunnelSettings;
|
||||
@ -221,9 +222,9 @@ public class ConfigNetHandler extends FormHandler {
|
||||
updateRates();
|
||||
|
||||
if (_timeSyncEnabled) {
|
||||
System.setProperty("timestamper.enabled", "true");
|
||||
_context.router().setConfigSetting(Timestamper.PROP_DISABLED, "false");
|
||||
} else {
|
||||
System.setProperty("timestamper.enabled", "false");
|
||||
_context.router().setConfigSetting(Timestamper.PROP_DISABLED, "false");
|
||||
}
|
||||
|
||||
boolean saved = _context.router().saveConfig();
|
||||
|
@ -6,6 +6,7 @@ import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import net.i2p.time.Timestamper;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
@ -50,8 +51,8 @@ public class ConfigNetHelper {
|
||||
}
|
||||
|
||||
public String getEnableTimeSyncChecked() {
|
||||
String enabled = System.getProperty("timestamper.enabled");
|
||||
if ( (enabled == null) || (!"true".equals(enabled)) )
|
||||
String enabled = _context.getProperty(Timestamper.PROP_DISABLED, "true");
|
||||
if ( (enabled == null) || (!"true".equalsIgnoreCase(enabled)) )
|
||||
return "";
|
||||
else
|
||||
return " checked ";
|
||||
|
@ -34,10 +34,8 @@
|
||||
to <a href="http://www.whatismyip.com/">www.whatismyip.com</a>.</i>
|
||||
<hr />
|
||||
<b>Enable internal time synchronization?</b> <input type="checkbox" <jsp:getProperty name="nethelper" property="enableTimeSyncChecked" /> name="enabletimesync" /><br />
|
||||
<i>If disabled, your machine <b>must</b> be NTP synchronized. This option only
|
||||
takes effect for the current run - if your machine is always synchronized within
|
||||
(a few seconds), you can update your configuration so that it doesn't start the
|
||||
"Timestamper" app (which would make this option irrelevent)</i>
|
||||
<i>If disabled, your machine <b>must</b> be NTP synchronized - your clock must always
|
||||
be within a few seconds of "correct".</i>
|
||||
<hr />
|
||||
<b>Bandwidth limiter</b><br />
|
||||
<b>Inbound rate</b>:
|
||||
|
@ -1,41 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project basedir="." default="all" name="time">
|
||||
<target name="all" depends="clean, build" />
|
||||
<target name="build" depends="builddep, jar" />
|
||||
<target name="builddep">
|
||||
<ant dir="../../../core/java/" target="build" />
|
||||
</target>
|
||||
<target name="compile">
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/obj" />
|
||||
<javac srcdir="./src" debug="true" source="1.3" target="1.3" deprecation="on" destdir="./build/obj" includes="**/*.java" classpath="../../../core/java/build/i2p.jar" />
|
||||
</target>
|
||||
<target name="jar" depends="compile">
|
||||
<jar destfile="./build/timestamper.jar" basedir="./build/obj" includes="**/*.class">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="net.i2p.time.Timestamper" />
|
||||
<attribute name="Class-Path" value="i2p.jar timestamper.jar" />
|
||||
</manifest>
|
||||
</jar>
|
||||
</target>
|
||||
<target name="javadoc">
|
||||
<mkdir dir="./build" />
|
||||
<mkdir dir="./build/javadoc" />
|
||||
<javadoc
|
||||
sourcepath="./src:../../../core/java/src:../../../core/java/test" destdir="./build/javadoc"
|
||||
packagenames="*"
|
||||
use="true"
|
||||
access="package"
|
||||
splitindex="true"
|
||||
windowtitle="I2P timestamper" />
|
||||
</target>
|
||||
<target name="clean">
|
||||
<delete dir="./build" />
|
||||
</target>
|
||||
<target name="cleandep" depends="clean">
|
||||
<ant dir="../../../core/java/" target="cleandep" />
|
||||
</target>
|
||||
<target name="distclean" depends="clean">
|
||||
<ant dir="../../../core/java/" target="distclean" />
|
||||
</target>
|
||||
</project>
|
@ -1,122 +0,0 @@
|
||||
package net.i2p.time;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* Periodically query a series of NTP servers and post the offset
|
||||
* to a given URL. It tries the NTP servers in order, contacting them
|
||||
* using UDP port 123, and sends the current date to the URL specified
|
||||
* (specifically, URL+"&now=" + yyyyMMdd_HH:mm:ss.SSS in the UK locale).
|
||||
* It does this every 5 minutes, forever.
|
||||
*
|
||||
* Usage: <pre>
|
||||
* Timestamper URL ntpServer1[ ntpServer2]*
|
||||
* </pre>
|
||||
*/
|
||||
public class Timestamper implements Runnable {
|
||||
private static Log _log = new Log(Timestamper.class);
|
||||
private static String _targetURL;
|
||||
private static String _serverList[];
|
||||
|
||||
private int DELAY_MS = 5*60*1000;
|
||||
|
||||
public Timestamper() {}
|
||||
|
||||
public void startTimestamper() {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Starting timestamper pointing at " + _targetURL);
|
||||
synchronized (Timestamper.class) {
|
||||
String enabled = System.getProperty("timestamper.started");
|
||||
if (enabled != null) {
|
||||
_log.warn("Timestamper already running");
|
||||
return;
|
||||
} else {
|
||||
System.setProperty("timestamper.started", "true");
|
||||
System.setProperty("timestamper.enabled", "true");
|
||||
}
|
||||
}
|
||||
I2PThread t = new I2PThread(this, "Timestamper");
|
||||
t.setPriority(I2PThread.MIN_PRIORITY);
|
||||
t.start();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Starting up timestamper");
|
||||
try {
|
||||
while (true) {
|
||||
String enabled = System.getProperty("timestamper.enabled");
|
||||
if ( (enabled == null) || (!"true".equals(enabled)) ) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Not stamping the time");
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Querying servers " + _serverList);
|
||||
try {
|
||||
long now = NtpClient.currentTime(_serverList);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Stamp time");
|
||||
stampTime(now);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
_log.log(Log.CRIT, "Unable to reach any of the NTP servers - network disconnected?");
|
||||
}
|
||||
}
|
||||
try { Thread.sleep(DELAY_MS); } catch (InterruptedException ie) {}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
_log.log(Log.CRIT, "Timestamper died!", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an HTTP request to a given URL specifying the current time
|
||||
*/
|
||||
private void stampTime(long now) {
|
||||
try {
|
||||
String toRequest = _targetURL + "&now=" + getNow(now);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Stamping [" + toRequest + "]");
|
||||
URL url = new URL(toRequest);
|
||||
Object o = url.getContent();
|
||||
// ignore the content
|
||||
} catch (MalformedURLException mue) {
|
||||
_log.error("Invalid URL", mue);
|
||||
} catch (IOException ioe) {
|
||||
_log.error("Error stamping the time", ioe);
|
||||
}
|
||||
}
|
||||
|
||||
private SimpleDateFormat _fmt = new SimpleDateFormat("yyyyMMdd_HH:mm:ss.SSS", Locale.UK);
|
||||
private String getNow(long now) {
|
||||
synchronized (_fmt) {
|
||||
return _fmt.format(new Date(now));
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
if ( (args == null) || (args.length < 2) ) {
|
||||
usage();
|
||||
return;
|
||||
//args = new String[] { "http://dev.i2p.net:80/somePath?pass=password", "ntp1.sth.netnod.se", "ntp2.sth.netnod.se" };
|
||||
}
|
||||
String servers[] = new String[args.length-1];
|
||||
System.arraycopy(args, 1, servers, 0, servers.length);
|
||||
_targetURL = args[0];
|
||||
_serverList = servers;
|
||||
Timestamper ts = new Timestamper();
|
||||
ts.startTimestamper();
|
||||
}
|
||||
|
||||
private static void usage() {
|
||||
System.err.println("Usage: Timestamper URL ntpServer[ ntpServer]*");
|
||||
_log.error("Usage: Timestamper URL ntpServer[ ntpServer]*");
|
||||
}
|
||||
}
|
@ -27,7 +27,6 @@
|
||||
<ant dir="apps/sam/java/" target="jar" />
|
||||
<ant dir="apps/heartbeat/java/" target="jar" />
|
||||
<ant dir="apps/netmonitor/java/" target="jar" />
|
||||
<ant dir="apps/time/java/" target="jar" />
|
||||
<ant dir="apps/routerconsole/java/" target="jar" />
|
||||
<ant dir="installer/java/" target="jar" />
|
||||
</target>
|
||||
@ -43,7 +42,6 @@
|
||||
<copy file="apps/sam/java/build/sam.jar" todir="build/" />
|
||||
<copy file="apps/heartbeat/java/build/heartbeat.jar" todir="build/" />
|
||||
<copy file="apps/netmonitor/java/build/netmonitor.jar" todir="build/" />
|
||||
<copy file="apps/time/java/build/timestamper.jar" todir="build/" />
|
||||
<copy file="installer/java/build/install.jar" todir="build/" />
|
||||
<copy file="installer/java/build/guiinstall.jar" todir="build/" />
|
||||
<copy file="installer/java/build/fetchseeds.jar" todir="build/" />
|
||||
@ -74,7 +72,6 @@
|
||||
<ant dir="apps/heartbeat/java/" target="distclean" />
|
||||
<ant dir="apps/netmonitor/java/" target="distclean" />
|
||||
<ant dir="apps/routerconsole/java/" target="distclean" />
|
||||
<ant dir="apps/time/java/" target="distclean" />
|
||||
<ant dir="installer/java/" target="distclean" />
|
||||
<delete>
|
||||
<fileset dir="." includes="**/*.class" />
|
||||
|
@ -1,5 +1,33 @@
|
||||
package net.i2p.time;
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004, Adam Buckley
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of Adam Buckley nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.net.DatagramPacket;
|
||||
@ -17,20 +45,6 @@ import java.net.InetAddress;
|
||||
* Note that on windows platforms, the curent time-of-day timestamp is limited
|
||||
* to an resolution of 10ms and adversely affects the accuracy of the results.
|
||||
*
|
||||
*
|
||||
* This code is copyright (c) Adam Buckley 2004
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version. A HTML version of the GNU General Public License can be
|
||||
* seen at http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* @author Adam Buckley
|
||||
* (minor refactoring by jrandom)
|
||||
*/
|
@ -1,4 +1,33 @@
|
||||
package net.i2p.time;
|
||||
/*
|
||||
* Copyright (c) 2004, Adam Buckley
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* - Neither the name of Adam Buckley nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
@ -34,21 +63,6 @@ import java.util.Date;
|
||||
* socket.receive(packet);
|
||||
* System.out.println(msg.toString());
|
||||
*
|
||||
*
|
||||
* This code is copyright (c) Adam Buckley 2004
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version. A HTML version of the GNU General Public License can be
|
||||
* seen at http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
*
|
||||
* Comments for member variables are taken from RFC2030 by David Mills,
|
||||
* University of Delaware.
|
||||
*
|
190
core/java/src/net/i2p/time/Timestamper.java
Normal file
190
core/java/src/net/i2p/time/Timestamper.java
Normal file
@ -0,0 +1,190 @@
|
||||
package net.i2p.time;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
* Periodically query a series of NTP servers and update any associated
|
||||
* listeners. It tries the NTP servers in order, contacting them using
|
||||
* SNTP (UDP port 123). By default, it does this every 5 minutes,
|
||||
* forever.
|
||||
*/
|
||||
public class Timestamper implements Runnable {
|
||||
private I2PAppContext _context;
|
||||
private Log _log;
|
||||
private List _servers;
|
||||
private List _listeners;
|
||||
private int _queryFrequency;
|
||||
private boolean _disabled;
|
||||
|
||||
private static final int DEFAULT_QUERY_FREQUENCY = 5*60*1000;
|
||||
private static final String DEFAULT_SERVER_LIST = "pool.ntp.org, pool.ntp.org";
|
||||
private static final boolean DEFAULT_DISABLED = false;
|
||||
|
||||
public static final String PROP_QUERY_FREQUENCY = "time.queryFrequencyMs";
|
||||
public static final String PROP_SERVER_LIST = "time.sntpServerList";
|
||||
public static final String PROP_DISABLED = "time.disabled";
|
||||
|
||||
public Timestamper(I2PAppContext ctx) {
|
||||
this(ctx, null);
|
||||
}
|
||||
|
||||
public Timestamper(I2PAppContext ctx, UpdateListener lsnr) {
|
||||
_context = ctx;
|
||||
_servers = new ArrayList(1);
|
||||
_listeners = new ArrayList(1);
|
||||
if (lsnr != null)
|
||||
_listeners.add(lsnr);
|
||||
updateConfig();
|
||||
startTimestamper();
|
||||
}
|
||||
|
||||
public int getServerCount() {
|
||||
synchronized (_servers) {
|
||||
return _servers.size();
|
||||
}
|
||||
}
|
||||
public String getServer(int index) {
|
||||
synchronized (_servers) {
|
||||
return (String)_servers.get(index);
|
||||
}
|
||||
}
|
||||
|
||||
public int getQueryFrequencyMs() { return _queryFrequency; }
|
||||
|
||||
public boolean getIsDisabled() { return _disabled; }
|
||||
|
||||
public void addListener(UpdateListener lsnr) {
|
||||
synchronized (_listeners) {
|
||||
_listeners.add(lsnr);
|
||||
}
|
||||
}
|
||||
public void removeListener(UpdateListener lsnr) {
|
||||
synchronized (_listeners) {
|
||||
_listeners.remove(lsnr);
|
||||
}
|
||||
}
|
||||
public int getListenerCount() {
|
||||
synchronized (_listeners) {
|
||||
return _listeners.size();
|
||||
}
|
||||
}
|
||||
public UpdateListener getListener(int index) {
|
||||
synchronized (_listeners) {
|
||||
return (UpdateListener)_listeners.get(index);
|
||||
}
|
||||
}
|
||||
|
||||
private void startTimestamper() {
|
||||
I2PThread t = new I2PThread(this, "Timestamper");
|
||||
t.setPriority(I2PThread.MIN_PRIORITY);
|
||||
t.start();
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Starting up timestamper");
|
||||
try {
|
||||
while (true) {
|
||||
if (!_disabled) {
|
||||
String serverList[] = null;
|
||||
synchronized (_servers) {
|
||||
serverList = new String[_servers.size()];
|
||||
for (int i = 0; i < serverList.length; i++)
|
||||
serverList[i] = (String)_servers.get(i);
|
||||
}
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Querying servers " + _servers);
|
||||
try {
|
||||
long now = NtpClient.currentTime(serverList);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Stamp time");
|
||||
stampTime(now);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
_log.log(Log.CRIT, "Unable to reach any of the NTP servers - network disconnected?");
|
||||
}
|
||||
}
|
||||
updateConfig();
|
||||
try { Thread.sleep(_queryFrequency); } catch (InterruptedException ie) {}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
_log.log(Log.CRIT, "Timestamper died!", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an HTTP request to a given URL specifying the current time
|
||||
*/
|
||||
private void stampTime(long now) {
|
||||
synchronized (_listeners) {
|
||||
for (int i = 0; i < _listeners.size(); i++) {
|
||||
UpdateListener lsnr = (UpdateListener)_listeners.get(i);
|
||||
lsnr.setNow(now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload all the config elements from the appContext
|
||||
*
|
||||
*/
|
||||
private void updateConfig() {
|
||||
String serverList = _context.getProperty(PROP_SERVER_LIST);
|
||||
if ( (serverList == null) || (serverList.trim().length() <= 0) )
|
||||
serverList = DEFAULT_SERVER_LIST;
|
||||
synchronized (_servers) {
|
||||
StringTokenizer tok = new StringTokenizer(serverList, ",");
|
||||
while (tok.hasMoreTokens()) {
|
||||
String val = (String)tok.nextToken();
|
||||
val = val.trim();
|
||||
if (val.length() > 0)
|
||||
_servers.add(val);
|
||||
}
|
||||
}
|
||||
|
||||
String freq = _context.getProperty(PROP_QUERY_FREQUENCY);
|
||||
if ( (freq == null) || (freq.trim().length() <= 0) )
|
||||
freq = DEFAULT_QUERY_FREQUENCY + "";
|
||||
try {
|
||||
int ms = Integer.parseInt(freq);
|
||||
if (ms > 60*1000) {
|
||||
_queryFrequency = ms;
|
||||
} else {
|
||||
if ( (_log != null) && (_log.shouldLog(Log.ERROR)) )
|
||||
_log.error("Query frequency once every " + ms + "ms is too fast!");
|
||||
_queryFrequency = DEFAULT_QUERY_FREQUENCY;
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
if ( (_log != null) && (_log.shouldLog(Log.WARN)) )
|
||||
_log.warn("Invalid query frequency [" + freq + "], falling back on " + DEFAULT_QUERY_FREQUENCY);
|
||||
_queryFrequency = DEFAULT_QUERY_FREQUENCY;
|
||||
}
|
||||
|
||||
String disabled = _context.getProperty(PROP_DISABLED);
|
||||
if (disabled == null)
|
||||
disabled = DEFAULT_DISABLED + "";
|
||||
_disabled = Boolean.getBoolean(disabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface to receive update notifications for when we query the time
|
||||
*
|
||||
*/
|
||||
public interface UpdateListener {
|
||||
/**
|
||||
* The time has been queried and we have a current value for 'now'
|
||||
*
|
||||
*/
|
||||
public void setNow(long now);
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.time.Timestamper;
|
||||
|
||||
/**
|
||||
* Alternate location for determining the time which takes into account an offset.
|
||||
@ -13,18 +14,23 @@ import net.i2p.I2PAppContext;
|
||||
* (such as an NTP synchronized clock).
|
||||
*
|
||||
*/
|
||||
public class Clock {
|
||||
public class Clock implements Timestamper.UpdateListener {
|
||||
private I2PAppContext _context;
|
||||
private Timestamper _timestamper;
|
||||
|
||||
public Clock(I2PAppContext context) {
|
||||
_context = context;
|
||||
_offset = 0;
|
||||
_alreadyChanged = false;
|
||||
_listeners = new HashSet(64);
|
||||
_timestamper = new Timestamper(context, this);
|
||||
}
|
||||
public static Clock getInstance() {
|
||||
return I2PAppContext.getGlobalContext().clock();
|
||||
}
|
||||
|
||||
public Timestamper getTimestamper() { return _timestamper; }
|
||||
|
||||
/** we fetch it on demand to avoid circular dependencies (logging uses the clock) */
|
||||
private Log getLog() { return _context.logManager().getLog(Clock.class); }
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
<ant dir="../../apps/sam/java/" target="build" />
|
||||
<ant dir="../../apps/netmonitor/java/" target="build" />
|
||||
<ant dir="../../apps/heartbeat/java/" target="build" />
|
||||
<ant dir="../../apps/time/java/" target="build" />
|
||||
</target>
|
||||
<target name="compile">
|
||||
<mkdir dir="./build" />
|
||||
@ -40,7 +39,6 @@
|
||||
<fileset file="../../apps/sam/java/build/sam.jar" />
|
||||
<fileset file="../../apps/heartbeat/java/build/heartbeat.jar" />
|
||||
<fileset file="../../apps/netmonitor/java/build/netmonitor.jar" />
|
||||
<fileset file="../../apps/time/java/build/timestamper.jar" />
|
||||
<fileset file="../doc/COPYING" />
|
||||
<fileset file="../../readme.txt" />
|
||||
<fileset file="../../hosts.txt" />
|
||||
@ -64,7 +62,6 @@
|
||||
<fileset file="../../apps/sam/java/build/sam.jar" />
|
||||
<fileset file="../../apps/heartbeat/java/build/heartbeat.jar" />
|
||||
<fileset file="../../apps/netmonitor/java/build/netmonitor.jar" />
|
||||
<fileset file="../../apps/time/java/build/timestamper.jar" />
|
||||
<fileset file="../doc/COPYING" />
|
||||
<fileset file="../../readme.txt" />
|
||||
<fileset file="../../hosts.txt" />
|
||||
@ -86,7 +83,6 @@
|
||||
<ant dir="../../apps/sam/java/" target="cleandep" />
|
||||
<ant dir="../../apps/heartbeat/java" target="cleandep" />
|
||||
<ant dir="../../apps/netmonitor/java" target="cleandep" />
|
||||
<ant dir="../../apps/time/java" target="cleandep" />
|
||||
</target>
|
||||
<target name="distclean" depends="clean">
|
||||
<ant dir="../../core/java/" target="distclean" />
|
||||
@ -96,6 +92,5 @@
|
||||
<ant dir="../../apps/sam/java/" target="distclean" />
|
||||
<ant dir="../../apps/heartbeat/java" target="distclean" />
|
||||
<ant dir="../../apps/netmonitor/java" target="distclean" />
|
||||
<ant dir="../../apps/time/java" target="distclean" />
|
||||
</target>
|
||||
</project>
|
||||
|
@ -325,10 +325,6 @@ public abstract class Install {
|
||||
_i2cpPort = ((Integer)_answers.get("i2cpPort")).intValue();
|
||||
_inBPS = ((Integer)_answers.get("inBPS")).intValue();
|
||||
_outBPS = ((Integer)_answers.get("outBPS")).intValue();
|
||||
long num = new java.util.Random().nextLong();
|
||||
if (num < 0)
|
||||
num = 0 - num;
|
||||
_answers.put("timestamperPassword", new Long(num));
|
||||
}
|
||||
|
||||
private void useTemplate(String templateName, File destFile) {
|
||||
|
@ -115,5 +115,3 @@ libs.0012.name=harvester.config
|
||||
libs.0012.islib=false
|
||||
libs.0013.name=heartbeat.config
|
||||
libs.0013.islib=false
|
||||
libs.0014.name=timestamper.jar
|
||||
libs.0014.islib=true
|
@ -109,13 +109,7 @@ tunnels.tunnelDuration=600000
|
||||
# http://localhost:7655/shutdown?password=thisIsASecret)
|
||||
#router.shutdownPassword=thisIsASecret
|
||||
|
||||
#
|
||||
# the remaining lines describe how you can get your router to fire up client
|
||||
# applications it is up and running, all within the router's JVM. Uncomment the
|
||||
# ones you want (revising the numbers and ports accordingly)
|
||||
|
||||
# Keep the router's clock in sync by querying one of the specified NTP servers once
|
||||
# a minute (uses UDP port 123)
|
||||
# Comma delimited list of SNTP servers to query. pool.ntp.org is a DNS trick to
|
||||
# This defaults to the DNS round-robin ntp pool - see http://www.pool.ntp.org/
|
||||
# Please change the NTP server specified to include ones closer to you - see
|
||||
# http://www.eecis.udel.edu/~mills/ntp/clock2a.html for a list (you can specify as
|
||||
@ -126,28 +120,30 @@ tunnels.tunnelDuration=600000
|
||||
# BR: ntp1.pucpr.br
|
||||
# BE: ntp2.belbone.be
|
||||
# AU: ntp.saard.net
|
||||
clientApp.0.main=net.i2p.time.Timestamper
|
||||
clientApp.0.name=Timestamper
|
||||
clientApp.0.onBoot=true
|
||||
clientApp.0.args=http://localhost:7655/setTime?##timestamperPassword## pool.ntp.org pool.ntp.org pool.ntp.org
|
||||
time.sntpServerList=pool.ntp.org,pool.ntp.org,pool.ntp.org
|
||||
|
||||
# The admin time passphrase, used to prevent unauthorized people from updating your
|
||||
# routers time. The value should be included in the timestamper's args above,
|
||||
# otherwise it wont honor timestamp updates. You shouldnt include any spaces or funky
|
||||
# characters - just pick some random numbers.
|
||||
adminTimePassphrase=##timestamperPassword##
|
||||
# Query an SNTP server every 5 minutes
|
||||
# time.queryFrequencyMs=300000
|
||||
|
||||
# If you really really know that your computer's clock is ALWAYS correct, set this property
|
||||
# time.disabled=true
|
||||
|
||||
#
|
||||
# the remaining lines describe how you can get your router to fire up client
|
||||
# applications it is up and running, all within the router's JVM. Uncomment the
|
||||
# ones you want (revising the numbers and ports accordingly)
|
||||
|
||||
# SAM bridge (a simplified socket based protocol for using I2P - listens on port 7656. see
|
||||
# the specs at http://www.i2p.net/node/view/144 for more info)
|
||||
clientApp.1.main=net.i2p.sam.SAMBridge
|
||||
clientApp.1.name=SAMBridge
|
||||
clientApp.1.args=sam.keys 0.0.0.0 7656 i2cp.tcp.host=localhost i2cp.tcp.port=##_router_i2cp_port##
|
||||
clientApp.0.main=net.i2p.sam.SAMBridge
|
||||
clientApp.0.name=SAMBridge
|
||||
clientApp.0.args=sam.keys 0.0.0.0 7656 i2cp.tcp.host=localhost i2cp.tcp.port=##_router_i2cp_port##
|
||||
|
||||
# The eepProxy (HTTP proxy that lets you browse both eepsites and the normal web via squid.i2p) and
|
||||
# the ircProxy (which connects to the anonymously hosted ircd at irc.duck.i2p)
|
||||
clientApp.2.main=net.i2p.i2ptunnel.I2PTunnel
|
||||
clientApp.2.name=Tunnels
|
||||
clientApp.2.args=-nocli -e "config localhost ##_router_i2cp_port##" -e "httpclient 4444" -e "client 6668 irc.duck.i2p"
|
||||
clientApp.1.main=net.i2p.i2ptunnel.I2PTunnel
|
||||
clientApp.1.name=Tunnels
|
||||
clientApp.1.args=-nocli -e "config localhost ##_router_i2cp_port##" -e "httpclient 4444" -e "client 6668 irc.duck.i2p"
|
||||
# note: if you want the proxies to be reachable from other machines, add:
|
||||
# -e "listen_on 0.0.0.0"
|
||||
# before the -e "httpclient 4444". otherwise, both of these proxies will only listen for connections on 127.0.0.1
|
||||
@ -157,10 +153,10 @@ clientApp.2.args=-nocli -e "config localhost ##_router_i2cp_port##" -e "httpclie
|
||||
# and add jetty-all.jar and routerconsole.jar in the router's classpath in the startRouter
|
||||
# script
|
||||
# (don't bother trying to figure this out prior to the 0.4 release)
|
||||
#clientApp.3.main=net.i2p.router.web.RouterConsoleRunner
|
||||
#clientApp.3.name=webConsole
|
||||
#clientApp.3.args=7657 127.0.0.1 ./webapps/
|
||||
#clientApp.3.onBoot=true
|
||||
#clientApp.2.main=net.i2p.router.web.RouterConsoleRunner
|
||||
#clientApp.2.name=webConsole
|
||||
#clientApp.2.args=7657 127.0.0.1 ./webapps/
|
||||
#clientApp.2.onBoot=true
|
||||
|
||||
# To require simple HTTP authentication for accessing any of the pages underneath the web console
|
||||
# (including any other webapps deployed), uncomment the following line and set the password
|
||||
@ -169,16 +165,3 @@ clientApp.2.args=-nocli -e "config localhost ##_router_i2cp_port##" -e "httpclie
|
||||
# settings, etc). This is only used for the new jetty console (started in clientApp.3.* above)
|
||||
#
|
||||
#consolePassword=fooBarBaz
|
||||
|
||||
# Network monitor (harvests data from the network database and stores it under
|
||||
# monitorData/, and with the netviewer GUI you can browse through its results)
|
||||
#clientApp.4.main=net.i2p.netmonitor.NetMonitor
|
||||
#clientApp.4.name=NetMonitor
|
||||
#clientApp.4.args=
|
||||
|
||||
# Heartbeat engine (ueber-simple ping/pong system, configured in heartbeat.config. By itself
|
||||
# it just writes out stat data where its told to, but there's a seperate HeartbeatMonitor
|
||||
# GUI to let you visualize things)
|
||||
#clientApp.5.main=net.i2p.heartbeat.Heartbeat
|
||||
#clientApp.5.name=Heartbeat
|
||||
#clientApp.5.args=heartbeat.config
|
||||
|
@ -4,4 +4,4 @@ cd ##_scripts_installdir##
|
||||
|
||||
REM the -XX args are workarounds for bugs in java 1.4.2's garbage collector
|
||||
|
||||
java -cp lib\i2p.jar;lib\router.jar;lib\mstreaming.jar;lib\heartbeat.jar;lib\i2ptunnel.jar;lib\netmonitor.jar;lib\sam.jar;lib\timestamper.jar -Djava.library.path=. -DloggerFilenameOverride=logs\log-router-#.txt -XX:NewSize=4M -XX:MaxNewSize=8M -XX:PermSize=8M -XX:MaxPermSize=32M net.i2p.router.Router
|
||||
java -cp lib\i2p.jar;lib\router.jar;lib\mstreaming.jar;lib\heartbeat.jar;lib\i2ptunnel.jar;lib\netmonitor.jar;lib\sam.jar -Djava.library.path=. -DloggerFilenameOverride=logs\log-router-#.txt -XX:NewSize=4M -XX:MaxNewSize=8M -XX:PermSize=8M -XX:MaxPermSize=32M net.i2p.router.Router
|
||||
|
@ -2,7 +2,7 @@
|
||||
cd ##_scripts_installdir##
|
||||
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
|
||||
# the -XX args are workarounds for bugs in java 1.4.2's garbage collector
|
||||
nohup nice java -cp lib/i2p.jar:lib/router.jar:lib/mstreaming.jar:lib/heartbeat.jar:lib/i2ptunnel.jar:lib/netmonitor.jar:lib/sam.jar:lib/timestamper.jar -Djava.library.path=. -DloggerFilenameOverride=logs/log-router-#.txt -XX:NewSize=4M -XX:MaxNewSize=8M -XX:PermSize=8M -XX:MaxPermSize=32M net.i2p.router.Router --quiet > /dev/null &
|
||||
nohup nice java -cp lib/i2p.jar:lib/router.jar:lib/mstreaming.jar:lib/heartbeat.jar:lib/i2ptunnel.jar:lib/netmonitor.jar:lib/sam.jar -Djava.library.path=. -DloggerFilenameOverride=logs/log-router-#.txt -XX:NewSize=4M -XX:MaxNewSize=8M -XX:PermSize=8M -XX:MaxPermSize=32M net.i2p.router.Router --quiet > /dev/null &
|
||||
# Save the pid just in case we ever want to stop the router
|
||||
echo $! > router.pid
|
||||
echo I2P Router started
|
||||
|
@ -6,10 +6,7 @@ import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import net.i2p.data.Hash;
|
||||
@ -58,13 +55,6 @@ class AdminRunner implements Runnable {
|
||||
}
|
||||
} else if (command.indexOf("/profile/") >= 0) {
|
||||
replyText(out, getProfile(command));
|
||||
} else if (command.indexOf("setTime") >= 0) {
|
||||
if (allowTimeUpdate(command)) {
|
||||
setTime(command);
|
||||
reply(out, "<html><body>Time updated</body></html>");
|
||||
} else {
|
||||
reply(out, "<html><body>Time not updated</body></html>");
|
||||
}
|
||||
} else if (command.indexOf("/shutdown") >= 0) {
|
||||
reply(out, shutdown(command));
|
||||
} else if (true || command.indexOf("routerConsole.html") > 0) {
|
||||
@ -80,25 +70,6 @@ class AdminRunner implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean allowTimeUpdate(String command) {
|
||||
String pass = _context.getProperty("adminTimePassphrase");
|
||||
if ( (pass == null) || (pass.trim().length() <= 0) ) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("No passphrase for update time from " + _socket.getInetAddress()
|
||||
+ ":" + _socket.getPort());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (command.indexOf(pass) != -1) {
|
||||
return true;
|
||||
} else {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("Invalid passphrase for update time from " + _socket.getInetAddress()
|
||||
+ ":" + _socket.getPort());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void reply(OutputStream out, String content) throws IOException {
|
||||
StringBuffer reply = new StringBuffer(10240);
|
||||
reply.append("HTTP/1.1 200 OK\n");
|
||||
@ -152,33 +123,6 @@ class AdminRunner implements Runnable {
|
||||
return "No such peer is being profiled\n";
|
||||
}
|
||||
|
||||
|
||||
private static final String FORMAT_STRING = "yyyyMMdd_HH:mm:ss.SSS";
|
||||
private SimpleDateFormat _fmt = new SimpleDateFormat(FORMAT_STRING, Locale.UK);
|
||||
|
||||
private long getTime(String now) throws ParseException {
|
||||
synchronized (_fmt) {
|
||||
return _fmt.parse(now).getTime();
|
||||
}
|
||||
}
|
||||
private void setTime(String cmd) {
|
||||
int start = cmd.indexOf("now=");
|
||||
String str = cmd.substring(start + 4, start+4+FORMAT_STRING.length());
|
||||
try {
|
||||
long now = getTime(str);
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.log(Log.INFO, "Admin time set to " + str);
|
||||
setTime(now);
|
||||
} catch (ParseException pe) {
|
||||
_log.error("Invalid time specified [" + str + "]", pe);
|
||||
}
|
||||
}
|
||||
|
||||
private void setTime(long now) {
|
||||
_context.clock().setNow(now);
|
||||
}
|
||||
|
||||
|
||||
private static final String SHUTDOWN_PASSWORD_PROP = "router.shutdownPassword";
|
||||
private String shutdown(String cmd) {
|
||||
String password = _context.router().getConfigSetting(SHUTDOWN_PASSWORD_PROP);
|
||||
|
Reference in New Issue
Block a user