forked from I2P_Developers/i2p.i2p
2004-11-21 jrandom
* Only allow small clock skews after the first 10 minutes of operation (to prevent later network lag bouncing us way off course - yes, we really need an NTP impl to balance out the network burps...) * Revamp the I2PTunnel web interface startup process so that everything is shown immediately, so that different pieces hanging don't hang the rest, and other minor bugfixes. * Take note of SAM startup error (in case you're already running a SAM bridge...) * Increase the bandwidth limiter burst values available to 10-60s (or whatever is placed in /configadvanced.jsp, of course)
This commit is contained in:
@ -99,7 +99,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
|||||||
t.start();
|
t.start();
|
||||||
open = true;
|
open = true;
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
while (!listenerReady) {
|
while (!listenerReady && open) {
|
||||||
try {
|
try {
|
||||||
wait();
|
wait();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@ -112,7 +112,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
|||||||
l.log("Ready! Port " + getLocalPort());
|
l.log("Ready! Port " + getLocalPort());
|
||||||
notifyEvent("openBaseClientResult", "ok");
|
notifyEvent("openBaseClientResult", "ok");
|
||||||
} else {
|
} else {
|
||||||
l.log("Error!");
|
l.log("Error listening - please see the logs!");
|
||||||
notifyEvent("openBaseClientResult", "error");
|
notifyEvent("openBaseClientResult", "error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,7 +232,13 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
|||||||
public final void run() {
|
public final void run() {
|
||||||
try {
|
try {
|
||||||
InetAddress addr = getListenHost(l);
|
InetAddress addr = getListenHost(l);
|
||||||
if (addr == null) return;
|
if (addr == null) {
|
||||||
|
open = false;
|
||||||
|
synchronized (this) {
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
ss = new ServerSocket(localPort, 0, addr);
|
ss = new ServerSocket(localPort, 0, addr);
|
||||||
|
|
||||||
// If a free port was requested, find out what we got
|
// If a free port was requested, find out what we got
|
||||||
@ -263,11 +269,15 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
|
|||||||
manageConnection(s);
|
manageConnection(s);
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
_log.error("Error listening for connections", ex);
|
_log.error("Error listening for connections on " + localPort, ex);
|
||||||
notifyEvent("openBaseClientResult", "error");
|
notifyEvent("openBaseClientResult", "error");
|
||||||
synchronized (sockLock) {
|
synchronized (sockLock) {
|
||||||
mySockets.clear();
|
mySockets.clear();
|
||||||
}
|
}
|
||||||
|
open = false;
|
||||||
|
synchronized (this) {
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ public class TunnelController implements Logging {
|
|||||||
private List _messages;
|
private List _messages;
|
||||||
private List _sessions;
|
private List _sessions;
|
||||||
private boolean _running;
|
private boolean _running;
|
||||||
|
private boolean _starting;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new controller for a tunnel out of the specific config options.
|
* Create a new controller for a tunnel out of the specific config options.
|
||||||
@ -58,8 +59,7 @@ public class TunnelController implements Logging {
|
|||||||
_running = false;
|
_running = false;
|
||||||
if (createKey && ("server".equals(getType())) )
|
if (createKey && ("server".equals(getType())) )
|
||||||
createPrivateKey();
|
createPrivateKey();
|
||||||
if (getStartOnLoad())
|
_starting = getStartOnLoad();
|
||||||
startTunnel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createPrivateKey() {
|
private void createPrivateKey() {
|
||||||
@ -104,12 +104,14 @@ public class TunnelController implements Logging {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void startTunnel() {
|
public void startTunnel() {
|
||||||
|
_starting = true;
|
||||||
try {
|
try {
|
||||||
doStartTunnel();
|
doStartTunnel();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
_log.error("Error starting up the tunnel", e);
|
_log.error("Error starting up the tunnel", e);
|
||||||
log("Error starting up the tunnel - " + e.getMessage());
|
log("Error starting up the tunnel - " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
_starting = false;
|
||||||
}
|
}
|
||||||
private void doStartTunnel() {
|
private void doStartTunnel() {
|
||||||
if (_running) {
|
if (_running) {
|
||||||
@ -299,6 +301,7 @@ public class TunnelController implements Logging {
|
|||||||
public boolean getStartOnLoad() { return "true".equalsIgnoreCase(_config.getProperty("startOnLoad", "true")); }
|
public boolean getStartOnLoad() { return "true".equalsIgnoreCase(_config.getProperty("startOnLoad", "true")); }
|
||||||
|
|
||||||
public boolean getIsRunning() { return _running; }
|
public boolean getIsRunning() { return _running; }
|
||||||
|
public boolean getIsStarting() { return _starting; }
|
||||||
|
|
||||||
public void getSummary(StringBuffer buf) {
|
public void getSummary(StringBuffer buf) {
|
||||||
String type = getType();
|
String type = getType();
|
||||||
|
@ -8,6 +8,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -20,6 +21,8 @@ import java.util.TreeMap;
|
|||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.client.I2PSession;
|
import net.i2p.client.I2PSession;
|
||||||
import net.i2p.client.I2PSessionException;
|
import net.i2p.client.I2PSessionException;
|
||||||
|
import net.i2p.data.DataHelper;
|
||||||
|
import net.i2p.util.I2PThread;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,28 +46,34 @@ public class TunnelControllerGroup {
|
|||||||
*/
|
*/
|
||||||
private Map _sessions;
|
private Map _sessions;
|
||||||
|
|
||||||
public static TunnelControllerGroup getInstance() { return _instance; }
|
public static TunnelControllerGroup getInstance() {
|
||||||
|
synchronized (TunnelControllerGroup.class) {
|
||||||
|
if (_instance == null)
|
||||||
|
_instance = new TunnelControllerGroup(DEFAULT_CONFIG_FILE);
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private TunnelControllerGroup(String configFile) {
|
private TunnelControllerGroup(String configFile) {
|
||||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(TunnelControllerGroup.class);
|
_log = I2PAppContext.getGlobalContext().logManager().getLog(TunnelControllerGroup.class);
|
||||||
_instance = this;
|
_controllers = Collections.synchronizedList(new ArrayList());
|
||||||
_controllers = new ArrayList();
|
|
||||||
_configFile = configFile;
|
_configFile = configFile;
|
||||||
_sessions = new HashMap(4);
|
_sessions = new HashMap(4);
|
||||||
loadControllers(_configFile);
|
loadControllers(_configFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
if ( (args == null) || (args.length <= 0) ) {
|
synchronized (TunnelControllerGroup.class) {
|
||||||
new TunnelControllerGroup(DEFAULT_CONFIG_FILE);
|
if (_instance != null) return; // already loaded through the web
|
||||||
} else if (args.length == 1) {
|
|
||||||
if (DEFAULT_CONFIG_FILE.equals(args[0]))
|
if ( (args == null) || (args.length <= 0) ) {
|
||||||
new TunnelControllerGroup(DEFAULT_CONFIG_FILE);
|
_instance = new TunnelControllerGroup(DEFAULT_CONFIG_FILE);
|
||||||
else
|
} else if (args.length == 1) {
|
||||||
new TunnelControllerGroup(args[0]);
|
_instance = new TunnelControllerGroup(args[0]);
|
||||||
} else {
|
} else {
|
||||||
System.err.println("Usage: TunnelControllerGroup [filename]");
|
System.err.println("Usage: TunnelControllerGroup [filename]");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,10 +98,24 @@ public class TunnelControllerGroup {
|
|||||||
_controllers.add(controller);
|
_controllers.add(controller);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
I2PThread startupThread = new I2PThread(new StartControllers(), "Startup tunnels");
|
||||||
|
startupThread.start();
|
||||||
|
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldLog(Log.INFO))
|
||||||
_log.info(i + " controllers loaded from " + configFile);
|
_log.info(i + " controllers loaded from " + configFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class StartControllers implements Runnable {
|
||||||
|
public void run() {
|
||||||
|
for (int i = 0; i < _controllers.size(); i++) {
|
||||||
|
TunnelController controller = (TunnelController)_controllers.get(i);
|
||||||
|
if (controller.getStartOnLoad())
|
||||||
|
controller.startTunnel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void reloadControllers() {
|
public void reloadControllers() {
|
||||||
unloadControllers();
|
unloadControllers();
|
||||||
loadControllers(_configFile);
|
loadControllers(_configFile);
|
||||||
@ -143,7 +166,6 @@ public class TunnelControllerGroup {
|
|||||||
controller.stopTunnel();
|
controller.stopTunnel();
|
||||||
msgs.addAll(controller.clearMessages());
|
msgs.addAll(controller.clearMessages());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldLog(Log.INFO))
|
||||||
_log.info(_controllers.size() + " controllers stopped");
|
_log.info(_controllers.size() + " controllers stopped");
|
||||||
return msgs;
|
return msgs;
|
||||||
@ -161,7 +183,7 @@ public class TunnelControllerGroup {
|
|||||||
controller.startTunnel();
|
controller.startTunnel();
|
||||||
msgs.addAll(controller.clearMessages());
|
msgs.addAll(controller.clearMessages());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldLog(Log.INFO))
|
||||||
_log.info(_controllers.size() + " controllers started");
|
_log.info(_controllers.size() + " controllers started");
|
||||||
return msgs;
|
return msgs;
|
||||||
@ -259,33 +281,13 @@ public class TunnelControllerGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
FileInputStream fis = null;
|
|
||||||
try {
|
try {
|
||||||
fis = new FileInputStream(cfgFile);
|
DataHelper.loadProps(props, cfgFile);
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(fis));
|
|
||||||
String line = null;
|
|
||||||
while ( (line = in.readLine()) != null) {
|
|
||||||
line = line.trim();
|
|
||||||
if (line.length() <= 0) continue;
|
|
||||||
if (line.startsWith("#") || line.startsWith(";"))
|
|
||||||
continue;
|
|
||||||
int eq = line.indexOf('=');
|
|
||||||
if ( (eq <= 0) || (eq >= line.length() - 1) )
|
|
||||||
continue;
|
|
||||||
String key = line.substring(0, eq);
|
|
||||||
String val = line.substring(eq+1);
|
|
||||||
props.setProperty(key, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_log.shouldLog(Log.INFO))
|
|
||||||
_log.info("Props loaded with " + props.size() + " lines");
|
|
||||||
return props;
|
return props;
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
if (_log.shouldLog(Log.ERROR))
|
if (_log.shouldLog(Log.ERROR))
|
||||||
_log.error("Error reading the controllers from " + configFile, ioe);
|
_log.error("Error reading the controllers from " + configFile, ioe);
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
|
||||||
if (fis != null) try { fis.close(); } catch (IOException ioe) {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,8 @@ public class WebStatusPageHelper {
|
|||||||
if (controller.getIsRunning()) {
|
if (controller.getIsRunning()) {
|
||||||
buf.append("<i>running</i> ");
|
buf.append("<i>running</i> ");
|
||||||
buf.append("<a href=\"index.jsp?num=").append(num).append("&action=stop\">stop</a> ");
|
buf.append("<a href=\"index.jsp?num=").append(num).append("&action=stop\">stop</a> ");
|
||||||
|
} else if (controller.getIsStarting()) {
|
||||||
|
buf.append("<i>startup in progress (please be patient)</i>");
|
||||||
} else {
|
} else {
|
||||||
buf.append("<i>not running</i> ");
|
buf.append("<i>not running</i> ");
|
||||||
buf.append("<a href=\"index.jsp?num=").append(num).append("&action=start\">start</a> ");
|
buf.append("<a href=\"index.jsp?num=").append(num).append("&action=start\">start</a> ");
|
||||||
|
@ -250,6 +250,7 @@ public class SAMBridge implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
|
if (serverSocket == null) return;
|
||||||
try {
|
try {
|
||||||
while (acceptConnections) {
|
while (acceptConnections) {
|
||||||
Socket s = serverSocket.accept();
|
Socket s = serverSocket.accept();
|
||||||
@ -293,7 +294,8 @@ public class SAMBridge implements Runnable {
|
|||||||
try {
|
try {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Shutting down, closing server socket");
|
_log.debug("Shutting down, closing server socket");
|
||||||
serverSocket.close();
|
if (serverSocket != null)
|
||||||
|
serverSocket.close();
|
||||||
} catch (IOException e) {}
|
} catch (IOException e) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import net.i2p.time.Timestamper;
|
|||||||
public class Clock implements Timestamper.UpdateListener {
|
public class Clock implements Timestamper.UpdateListener {
|
||||||
private I2PAppContext _context;
|
private I2PAppContext _context;
|
||||||
private Timestamper _timestamper;
|
private Timestamper _timestamper;
|
||||||
|
private long _startedOn;
|
||||||
|
|
||||||
public Clock(I2PAppContext context) {
|
public Clock(I2PAppContext context) {
|
||||||
_context = context;
|
_context = context;
|
||||||
@ -24,6 +25,7 @@ public class Clock implements Timestamper.UpdateListener {
|
|||||||
_alreadyChanged = false;
|
_alreadyChanged = false;
|
||||||
_listeners = new HashSet(64);
|
_listeners = new HashSet(64);
|
||||||
_timestamper = new Timestamper(context, this);
|
_timestamper = new Timestamper(context, this);
|
||||||
|
_startedOn = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
public static Clock getInstance() {
|
public static Clock getInstance() {
|
||||||
return I2PAppContext.getGlobalContext().clock();
|
return I2PAppContext.getGlobalContext().clock();
|
||||||
@ -40,6 +42,8 @@ public class Clock implements Timestamper.UpdateListener {
|
|||||||
|
|
||||||
/** if the clock is skewed by 3+ days, fuck 'em */
|
/** if the clock is skewed by 3+ days, fuck 'em */
|
||||||
public final static long MAX_OFFSET = 3 * 24 * 60 * 60 * 1000;
|
public final static long MAX_OFFSET = 3 * 24 * 60 * 60 * 1000;
|
||||||
|
/** after we've started up and shifted the clock, don't allow shifts of more than a minute */
|
||||||
|
public final static long MAX_LIVE_OFFSET = 60 * 1000;
|
||||||
/** if the clock skewed changes by less than 1s, ignore the update (so we don't slide all over the place) */
|
/** if the clock skewed changes by less than 1s, ignore the update (so we don't slide all over the place) */
|
||||||
public final static long MIN_OFFSET_CHANGE = 10 * 1000;
|
public final static long MIN_OFFSET_CHANGE = 10 * 1000;
|
||||||
|
|
||||||
@ -60,6 +64,15 @@ public class Clock implements Timestamper.UpdateListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only allow substantial modifications before the first 10 minutes
|
||||||
|
if (_alreadyChanged && (System.currentTimeMillis() - _startedOn > 10 * 60 * 1000)) {
|
||||||
|
if ( (offsetMs > MAX_LIVE_OFFSET) || (offsetMs < 0 - MAX_LIVE_OFFSET) ) {
|
||||||
|
getLog().log(Log.CRIT, "The clock has already been updated, but you want to change it by "
|
||||||
|
+ offsetMs + "? Did something break?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((delta < MIN_OFFSET_CHANGE) && (delta > 0 - MIN_OFFSET_CHANGE)) {
|
if ((delta < MIN_OFFSET_CHANGE) && (delta > 0 - MIN_OFFSET_CHANGE)) {
|
||||||
getLog().debug("Not changing offset since it is only " + delta + "ms");
|
getLog().debug("Not changing offset since it is only " + delta + "ms");
|
||||||
return;
|
return;
|
||||||
|
14
history.txt
14
history.txt
@ -1,4 +1,16 @@
|
|||||||
$Id: history.txt,v 1.77 2004/11/20 23:08:14 jrandom Exp $
|
$Id: history.txt,v 1.78 2004/11/21 14:42:57 jrandom Exp $
|
||||||
|
|
||||||
|
2004-11-21 jrandom
|
||||||
|
* Only allow small clock skews after the first 10 minutes of operation
|
||||||
|
(to prevent later network lag bouncing us way off course - yes, we
|
||||||
|
really need an NTP impl to balance out the network burps...)
|
||||||
|
* Revamp the I2PTunnel web interface startup process so that everything
|
||||||
|
is shown immediately, so that different pieces hanging don't hang
|
||||||
|
the rest, and other minor bugfixes.
|
||||||
|
* Take note of SAM startup error (in case you're already running a SAM
|
||||||
|
bridge...)
|
||||||
|
* Increase the bandwidth limiter burst values available to 10-60s (or
|
||||||
|
whatever is placed in /configadvanced.jsp, of course)
|
||||||
|
|
||||||
2004-11-21 jrandom
|
2004-11-21 jrandom
|
||||||
* Allow end of line comments in the hosts.txt and other config files,
|
* Allow end of line comments in the hosts.txt and other config files,
|
||||||
|
@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RouterVersion {
|
public class RouterVersion {
|
||||||
public final static String ID = "$Revision: 1.82 $ $Date: 2004/11/20 23:08:14 $";
|
public final static String ID = "$Revision: 1.83 $ $Date: 2004/11/21 14:42:58 $";
|
||||||
public final static String VERSION = "0.4.1.4";
|
public final static String VERSION = "0.4.1.4";
|
||||||
public final static long BUILD = 11;
|
public final static long BUILD = 12;
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
System.out.println("I2P Router version: " + VERSION);
|
System.out.println("I2P Router version: " + VERSION);
|
||||||
System.out.println("Router ID: " + RouterVersion.ID);
|
System.out.println("Router ID: " + RouterVersion.ID);
|
||||||
|
Reference in New Issue
Block a user