diff --git a/history.txt b/history.txt index db898d0a1..ea6e6e6e5 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,10 @@ -$Id: history.txt,v 1.85 2004/11/27 00:17:06 jrandom Exp $ +$Id: history.txt,v 1.86 2004/11/27 16:02:06 jrandom Exp $ + +2004-11-28 jrandom + * Accept IP address detection changes with a 2-out-of-3 minimum. + * As long as the router is up, keep retrying to bind the I2CP listener. + * Decrease the java service wrapper ping frequency to once every 10 + minutes, rather than once every 5 seconds. 2004-11-27 jrandom * Some cleanup and bugfixes for the IP address detection code where we diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index b4e73f507..20908408f 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -36,7 +36,7 @@ import net.i2p.data.i2np.TunnelMessage; import net.i2p.router.message.GarlicMessageHandler; import net.i2p.router.message.TunnelMessageHandler; import net.i2p.router.startup.StartupJob; -import net.i2p.router.startup.VerifyClasspath; +import net.i2p.router.startup.VerifyWrapperConfig; import net.i2p.stat.Rate; import net.i2p.stat.RateStat; import net.i2p.util.FileUtil; @@ -794,7 +794,7 @@ public class Router { public static void main(String args[]) { installUpdates(); - verifyClasspath(); + verifyWrapperConfig(); Router r = new Router(); r.runRouter(); } @@ -820,10 +820,10 @@ public class Router { } } - private static void verifyClasspath() { - boolean updated = VerifyClasspath.updateClasspath(); + private static void verifyWrapperConfig() { + boolean updated = VerifyWrapperConfig.verifyConfig(); if (updated) { - System.out.println("INFO: Classpath updated, but the service wrapper requires you to manually restart"); + System.out.println("INFO: Wrapper config updated, but the service wrapper requires you to manually restart"); System.out.println("INFO: Shutting down the router - please rerun it!"); System.exit(EXIT_HARD); } diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 1c2b1dc3e..ce72f6f5f 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -15,9 +15,9 @@ import net.i2p.CoreVersion; * */ public class RouterVersion { - public final static String ID = "$Revision: 1.90 $ $Date: 2004/11/27 00:17:06 $"; + public final static String ID = "$Revision: 1.91 $ $Date: 2004/11/27 16:02:06 $"; public final static String VERSION = "0.4.2"; - public final static long BUILD = 3; + public final static long BUILD = 4; public static void main(String args[]) { System.out.println("I2P Router version: " + VERSION); System.out.println("Router ID: " + RouterVersion.ID); diff --git a/router/java/src/net/i2p/router/client/ClientListenerRunner.java b/router/java/src/net/i2p/router/client/ClientListenerRunner.java index 36db7b6e9..52937d3b7 100644 --- a/router/java/src/net/i2p/router/client/ClientListenerRunner.java +++ b/router/java/src/net/i2p/router/client/ClientListenerRunner.java @@ -42,9 +42,6 @@ public class ClientListenerRunner implements Runnable { public void setPort(int port) { _port = port; } public int getPort() { return _port; } - /** max time to bind */ - private final static int MAX_FAIL_DELAY = 5*60*1000; - /** * Start up the socket listener, listens for connections, and * fires those connections off via {@link #runConnection runConnection}. @@ -55,7 +52,7 @@ public class ClientListenerRunner implements Runnable { public void runServer() { _running = true; int curDelay = 0; - while ( (_running) && (curDelay < MAX_FAIL_DELAY) ) { + while (_running) { try { _log.info("Starting up listening for connections on port " + _port); _socket = new ServerSocket(_port); diff --git a/router/java/src/net/i2p/router/startup/VerifyWrapperConfig.java b/router/java/src/net/i2p/router/startup/VerifyWrapperConfig.java new file mode 100644 index 000000000..eef7d31fd --- /dev/null +++ b/router/java/src/net/i2p/router/startup/VerifyWrapperConfig.java @@ -0,0 +1,42 @@ +package net.i2p.router.startup; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; +import net.i2p.data.DataHelper; + +/** + * Ugly code to make sure the service wrapper is configured + * properly + */ +public class VerifyWrapperConfig { + private static final String NL = System.getProperty("line.separator"); + + public static boolean verifyConfig() { + boolean cpUpdated = VerifyClasspath.updateClasspath(); + boolean pingUpdated = updatePing(); + return pingUpdated || cpUpdated; + } + + private static boolean updatePing() { + Properties p = new Properties(); + File configFile = new File("wrapper.config"); + try { + DataHelper.loadProps(p, configFile); + if (p.containsKey("wrapper.ping.interval")) + return false; + + FileWriter out = new FileWriter(configFile, true); + out.write(NL + "# Adding ping timeout as required by the update" + NL); + out.write("wrapper.ping.interval=600" + NL); + out.close(); + return true; + } catch (IOException ioe) { + ioe.printStackTrace(); + return false; + } + } +} diff --git a/router/java/src/net/i2p/router/transport/tcp/ConnectionBuilder.java b/router/java/src/net/i2p/router/transport/tcp/ConnectionBuilder.java index 8f965313c..e5f52e481 100644 --- a/router/java/src/net/i2p/router/transport/tcp/ConnectionBuilder.java +++ b/router/java/src/net/i2p/router/transport/tcp/ConnectionBuilder.java @@ -142,6 +142,7 @@ public class ConnectionBuilder { con.setRemoteRouterIdentity(_actualPeer.getIdentity()); con.setRemoteAddress(_remoteAddress); con.setAttemptedPeer(_target.getIdentity().getHash()); + con.setShownAddress(_localIP); if (_error == null) { if (_log.shouldLog(Log.INFO)) _log.info("Establishment successful! returning the con"); diff --git a/router/java/src/net/i2p/router/transport/tcp/TCPAddress.java b/router/java/src/net/i2p/router/transport/tcp/TCPAddress.java index bbf2b1050..f09a683a1 100644 --- a/router/java/src/net/i2p/router/transport/tcp/TCPAddress.java +++ b/router/java/src/net/i2p/router/transport/tcp/TCPAddress.java @@ -41,6 +41,8 @@ public class TCPAddress { _host = null; _port = -1; _addr = null; + if (_log.shouldLog(Log.WARN)) + _log.warn("Unknown host [" + host + "] for port [" + port + "]", uhe); } } diff --git a/router/java/src/net/i2p/router/transport/tcp/TCPListener.java b/router/java/src/net/i2p/router/transport/tcp/TCPListener.java index e45db4003..198f55888 100644 --- a/router/java/src/net/i2p/router/transport/tcp/TCPListener.java +++ b/router/java/src/net/i2p/router/transport/tcp/TCPListener.java @@ -69,6 +69,10 @@ class TCPListener { if (addr.getPort() > 0) { if (_listener != null) { + if ( (_listener.getMyAddress().getPort() == addr.getPort()) && + (_listener.getMyAddress().getHost() == null) ) { + _listener.getMyAddress().setHost(addr.getHost()); + } if (_log.shouldLog(Log.WARN)) _log.warn("Not starting another listener on " + addr + " while already listening on " + _listener.getMyAddress()); diff --git a/router/java/src/net/i2p/router/transport/tcp/TCPTransport.java b/router/java/src/net/i2p/router/transport/tcp/TCPTransport.java index 96822b375..b12bf9588 100644 --- a/router/java/src/net/i2p/router/transport/tcp/TCPTransport.java +++ b/router/java/src/net/i2p/router/transport/tcp/TCPTransport.java @@ -340,8 +340,10 @@ public class TCPTransport extends TransportImpl { * @param address address that the remote host said was ours */ void ourAddressReceived(String address) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Address received [" + address + "] our address: [" + _myAddress + "]"); synchronized (_listener) { // no need to lock on the whole TCPTransport - if (allowAddressUpdate()) { + if (allowAddressUpdate(address)) { int port = getPort(); TCPAddress addr = new TCPAddress(address, port); if (addr.getPort() > 0) { @@ -357,6 +359,9 @@ public class TCPTransport extends TransportImpl { if (_log.shouldLog(Log.INFO)) _log.info("Update our local address to " + address); updateAddress(addr); + } else { + if (_log.shouldLog(Log.WARN)) + _log.warn("Address received is NOT a valid address! [" + addr + "]"); } } else { if (_log.shouldLog(Log.ERROR)) @@ -455,9 +460,16 @@ public class TCPTransport extends TransportImpl { * */ boolean allowAddress(TCPAddress address) { - if (address == null) return false; - if ( (address.getPort() <= 0) || (address.getPort() > 65535) ) + if (address == null) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Address is null?!"); return false; + } + if ( (address.getPort() <= 0) || (address.getPort() > 65535) ) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Port is invalid? " + address.getPort()); + return false; + } if (!address.isPubliclyRoutable()) { String allowLocal = _context.getProperty(LISTEN_ALLOW_LOCAL, "false"); if (Boolean.valueOf(allowLocal).booleanValue()) { @@ -508,7 +520,7 @@ public class TCPTransport extends TransportImpl { * have no fully established connections. * */ - private boolean allowAddressUpdate() { + private boolean allowAddressUpdate(String proposedAddress) { int connectedPeers = countActivePeers(); boolean addressSpecified = (null != _context.getProperty(LISTEN_ADDRESS)); if (addressSpecified) { @@ -516,10 +528,26 @@ public class TCPTransport extends TransportImpl { _log.debug("Not allowing address update, sicne we have one specified (#cons=" + connectedPeers + ")"); return false; } - if (connectedPeers <= 0) { + if (connectedPeers < 3) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Allowing address update, since the # of connected peers is " + connectedPeers); return true; + } else if (connectedPeers == 3) { + // ok, now comes the vote: + // if we agree with the majority, allow the update + // otherwise, reject the update + int agreed = countActiveAgreeingPeers(proposedAddress); + if (agreed > 1) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Most common address selected, allowing address update w/ # of connected peers is " + connectedPeers); + return true; + } else { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Proposed address [" + proposedAddress + "] is only used by " + agreed + + ", rejecting address update w/ # of connected peers is " + + connectedPeers); + return false; + } } else { if (_log.shouldLog(Log.DEBUG)) _log.debug("Not allowing address update, since the # of connected peers is " + connectedPeers); @@ -577,6 +605,28 @@ public class TCPTransport extends TransportImpl { return numActive; } + /** + * How many peers that we are connected to think we are reachable at the given + * address? + * + */ + public int countActiveAgreeingPeers(String address) { + int agreed = 0; + synchronized (_connectionLock) { + if (_connectionsByIdent.size() <= 0) return 0; + for (Iterator iter = _connectionsByIdent.values().iterator(); iter.hasNext(); ) { + TCPConnection con = (TCPConnection)iter.next(); + if (con.getIsActive()) { + String shown = con.getShownAddress(); + if ( (shown != null) && (shown.equals(address)) ) + agreed++; + } + } + } + + return agreed; + } + /** * The transport is done sending this message. This exposes the * superclass's protected method to the current package.