From 352396bdc28d21295470c0d39ec0b9ef45050e64 Mon Sep 17 00:00:00 2001 From: jrandom <jrandom> Date: Fri, 13 Aug 2004 21:15:22 +0000 Subject: [PATCH] > 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) --- .../net/i2p/router/web/ConfigNetHandler.java | 5 +- .../net/i2p/router/web/ConfigNetHelper.java | 5 +- apps/routerconsole/jsp/config.jsp | 6 +- apps/time/java/build.xml | 41 ---- .../java/src/net/i2p/time/Timestamper.java | 122 ----------- build.xml | 3 - .../java/src/net/i2p/time/NtpClient.java | 44 ++-- .../java/src/net/i2p/time/NtpMessage.java | 44 ++-- core/java/src/net/i2p/time/Timestamper.java | 190 ++++++++++++++++++ core/java/src/net/i2p/util/Clock.java | 8 +- installer/java/build.xml | 5 - installer/java/src/Install.java | 4 - installer/java/src/install.config | 2 - installer/java/src/router.config.template | 61 ++---- installer/java/src/startRouter.bat.template | 2 +- installer/java/src/startRouter.sh.template | 2 +- .../src/net/i2p/router/admin/AdminRunner.java | 56 ------ 17 files changed, 287 insertions(+), 313 deletions(-) delete mode 100644 apps/time/java/build.xml delete mode 100644 apps/time/java/src/net/i2p/time/Timestamper.java rename {apps/time => core}/java/src/net/i2p/time/NtpClient.java (76%) rename {apps/time => core}/java/src/net/i2p/time/NtpMessage.java (90%) create mode 100644 core/java/src/net/i2p/time/Timestamper.java diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java index ca096ea009..3d7f4867c2 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHandler.java @@ -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(); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java index 6a788c3240..af0e441115 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java @@ -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 "; diff --git a/apps/routerconsole/jsp/config.jsp b/apps/routerconsole/jsp/config.jsp index 83716ebb97..7558e9ddcc 100644 --- a/apps/routerconsole/jsp/config.jsp +++ b/apps/routerconsole/jsp/config.jsp @@ -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>: diff --git a/apps/time/java/build.xml b/apps/time/java/build.xml deleted file mode 100644 index 768d6e2164..0000000000 --- a/apps/time/java/build.xml +++ /dev/null @@ -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> diff --git a/apps/time/java/src/net/i2p/time/Timestamper.java b/apps/time/java/src/net/i2p/time/Timestamper.java deleted file mode 100644 index 7ecca982fd..0000000000 --- a/apps/time/java/src/net/i2p/time/Timestamper.java +++ /dev/null @@ -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]*"); - } -} \ No newline at end of file diff --git a/build.xml b/build.xml index 60872ca7cb..62ab21181c 100644 --- a/build.xml +++ b/build.xml @@ -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" /> diff --git a/apps/time/java/src/net/i2p/time/NtpClient.java b/core/java/src/net/i2p/time/NtpClient.java similarity index 76% rename from apps/time/java/src/net/i2p/time/NtpClient.java rename to core/java/src/net/i2p/time/NtpClient.java index aa50ead4d2..5360f8d301 100644 --- a/apps/time/java/src/net/i2p/time/NtpClient.java +++ b/core/java/src/net/i2p/time/NtpClient.java @@ -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) */ diff --git a/apps/time/java/src/net/i2p/time/NtpMessage.java b/core/java/src/net/i2p/time/NtpMessage.java similarity index 90% rename from apps/time/java/src/net/i2p/time/NtpMessage.java rename to core/java/src/net/i2p/time/NtpMessage.java index c7076a9565..f7626b55b0 100644 --- a/apps/time/java/src/net/i2p/time/NtpMessage.java +++ b/core/java/src/net/i2p/time/NtpMessage.java @@ -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. * diff --git a/core/java/src/net/i2p/time/Timestamper.java b/core/java/src/net/i2p/time/Timestamper.java new file mode 100644 index 0000000000..1c0b7b0607 --- /dev/null +++ b/core/java/src/net/i2p/time/Timestamper.java @@ -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); + } +} \ No newline at end of file diff --git a/core/java/src/net/i2p/util/Clock.java b/core/java/src/net/i2p/util/Clock.java index a81497ba7e..304f06a26e 100644 --- a/core/java/src/net/i2p/util/Clock.java +++ b/core/java/src/net/i2p/util/Clock.java @@ -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); } diff --git a/installer/java/build.xml b/installer/java/build.xml index 6a4ba24af8..34e0670bba 100644 --- a/installer/java/build.xml +++ b/installer/java/build.xml @@ -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> diff --git a/installer/java/src/Install.java b/installer/java/src/Install.java index 37a6b92bb1..28de764e79 100644 --- a/installer/java/src/Install.java +++ b/installer/java/src/Install.java @@ -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) { diff --git a/installer/java/src/install.config b/installer/java/src/install.config index 99b0acb553..3ae943c1f7 100644 --- a/installer/java/src/install.config +++ b/installer/java/src/install.config @@ -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 \ No newline at end of file diff --git a/installer/java/src/router.config.template b/installer/java/src/router.config.template index a2de6049c0..bbe7b48d1a 100644 --- a/installer/java/src/router.config.template +++ b/installer/java/src/router.config.template @@ -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 + +# Query an SNTP server every 5 minutes +# time.queryFrequencyMs=300000 -# 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## +# 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 diff --git a/installer/java/src/startRouter.bat.template b/installer/java/src/startRouter.bat.template index e7267e5b1a..621fe4eec6 100644 --- a/installer/java/src/startRouter.bat.template +++ b/installer/java/src/startRouter.bat.template @@ -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 diff --git a/installer/java/src/startRouter.sh.template b/installer/java/src/startRouter.sh.template index 5785772588..ecf6d02a13 100644 --- a/installer/java/src/startRouter.sh.template +++ b/installer/java/src/startRouter.sh.template @@ -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 diff --git a/router/java/src/net/i2p/router/admin/AdminRunner.java b/router/java/src/net/i2p/router/admin/AdminRunner.java index 06143d4242..f8e16e5606 100644 --- a/router/java/src/net/i2p/router/admin/AdminRunner.java +++ b/router/java/src/net/i2p/router/admin/AdminRunner.java @@ -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); -- GitLab