diff --git a/history.txt b/history.txt index b48bc095c..f29a49c50 100644 --- a/history.txt +++ b/history.txt @@ -1,10 +1,15 @@ +2019-02-25 zzz + * NetDB: Fix dup publish of RI at startup + 2019-02-23 zzz + * Console: Flip order of router logs * NetDB: - Use published date, not earliest lease expiration, for LS2 comparisons - Fix earliest LS expiration adjustment when publishing for LS2 - Increase flood candidates for LS2 - Don't start new store after verify fail if we've already done so - Version checks for encrypted LS2 + * NTCP: Loop in pumper if more to write (ticket #2440) 2019-02-21 zzz * Crypto: Keygen for RedDSA, allow RedDSA for unblinded keys (Enc LS2) diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index c805cf865..b335fbd50 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -837,11 +837,24 @@ public class Router implements RouterClock.ClockShiftListener { * @since 0.9.18 */ public void setNetDbReady() { + boolean changed = false; synchronized(_stateLock) { - if (_state == State.STARTING_3) + if (_state == State.STARTING_3) { changeState(State.NETDB_READY); - else if (_state == State.EXPL_TUNNELS_READY) + changed = true; + } else if (_state == State.EXPL_TUNNELS_READY) { changeState(State.RUNNING); + changed = true; + } + } + if (changed) { + // any previous calls to netdb().publish() did not + // actually publish, because netdb init was not complete + Republish r = new Republish(_context); + // this is called from PersistentDataStore.ReadJob, + // so we probably don't need to throw it to the timer queue, + // but just to be safe + _context.simpleTimer2().addEvent(r, 0); } } @@ -905,7 +918,7 @@ public class Router implements RouterClock.ClockShiftListener { */ public void rebuildRouterInfo(boolean blockingRebuild) { if (_log.shouldLog(Log.INFO)) - _log.info("Rebuilding new routerInfo"); + _log.info("Rebuilding new routerInfo, publish inline? " + blockingRebuild, new Exception("I did it")); _routerInfoLock.writeLock().lock(); try { locked_rebuildRouterInfo(blockingRebuild); diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index f2522cd4e..7ca1a3ec2 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 9; + public final static long BUILD = 10; /** for example "-test" */ public final static String EXTRA = ""; diff --git a/router/java/src/net/i2p/router/networkdb/PublishLocalRouterInfoJob.java b/router/java/src/net/i2p/router/networkdb/PublishLocalRouterInfoJob.java index 353663cc5..0c94cf8ef 100644 --- a/router/java/src/net/i2p/router/networkdb/PublishLocalRouterInfoJob.java +++ b/router/java/src/net/i2p/router/networkdb/PublishLocalRouterInfoJob.java @@ -49,10 +49,13 @@ public class PublishLocalRouterInfoJob extends JobImpl { private static final long PUBLISH_DELAY = 52*60*1000; /** this needs to be long enough to give us time to start up, - but less than 20m (when we start accepting tunnels and could be a IBGW) - Actually no, we need this soon if we are a new router or - other routers have forgotten about us, else - we can't build IB exploratory tunnels. + * but less than 20m (when we start accepting tunnels and could be a IBGW) + * Actually no, we need this soon if we are a new router or + * other routers have forgotten about us, else + * we can't build IB exploratory tunnels. + * + * First publish after netdb ready is now done via state machine + * in Router.setNetDbReady(), so we probably don't need this anymore */ private static final long FIRST_TIME_DELAY = 90*1000; private volatile boolean _notFirstTime; @@ -142,6 +145,9 @@ public class PublishLocalRouterInfoJob extends JobImpl { if (_notFirstTime) { requeue(getDelay()); } else { + // First publish after netdb ready is now done via state machine + // in Router.setNetDbReady(), so we probably don't need this anymore + // but leave it in for now, a router may have trouble publishing right away requeue(FIRST_TIME_DELAY); _notFirstTime = true; } diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java index 0e402359b..51ea62fa2 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java @@ -137,8 +137,11 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad if (_context.router().isHidden()) return; // DE-nied! super.publish(localRouterInfo); // wait until we've read in the RI's so we can find the closest floodfill - if (!isInitialized()) + if (!isInitialized()) { + if (_log.shouldWarn()) + _log.warn("publish() before initialized: " + localRouterInfo, new Exception("I did it")); return; + } // no use sending if we have no addresses // (unless maybe we used to have addresses? not worth it if (localRouterInfo.getAddresses().isEmpty()) diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java index d0c323bb2..37f8ef181 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java @@ -678,7 +678,11 @@ public abstract class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacad * @throws IllegalArgumentException if the leaseSet is not valid */ public void publish(LeaseSet localLeaseSet) throws IllegalArgumentException { - if (!_initialized) return; + if (!_initialized) { + if (_log.shouldWarn()) + _log.warn("publish() before initialized: " + localLeaseSet, new Exception("I did it")); + return; + } Hash h = localLeaseSet.getDestination().calculateHash(); try { store(h, localLeaseSet); diff --git a/router/java/src/net/i2p/router/tasks/Republish.java b/router/java/src/net/i2p/router/tasks/Republish.java index 111456b89..c1b82d964 100644 --- a/router/java/src/net/i2p/router/tasks/Republish.java +++ b/router/java/src/net/i2p/router/tasks/Republish.java @@ -8,6 +8,7 @@ package net.i2p.router.tasks; * */ +import net.i2p.data.router.RouterInfo; import net.i2p.router.Router; import net.i2p.router.RouterContext; import net.i2p.util.SimpleTimer; @@ -27,7 +28,9 @@ public class Republish implements SimpleTimer.TimedEvent { public void timeReached() { try { - _context.netDb().publish(_context.router().getRouterInfo()); + RouterInfo ri = _context.router().getRouterInfo(); + if (ri != null) + _context.netDb().publish(ri); } catch (IllegalArgumentException iae) { Log log = _context.logManager().getLog(Router.class); log.log(Log.CRIT, "Local router info is invalid? rebuilding a new identity", iae); diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java index 5993b7b05..e157ff91e 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -991,20 +991,21 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority boolean fireTest = false; boolean isIPv6 = ourIP.length == 16; - RouterAddress current = getCurrentExternalAddress(isIPv6); - byte[] externalListenHost = current != null ? current.getIP() : null; - int externalListenPort = current != null ? current.getPort() : getRequestedPort(isIPv6); - if (_log.shouldLog(Log.INFO)) - _log.info("Change address? status = " + _reachabilityStatus + + synchronized (_rebuildLock) { + RouterAddress current = getCurrentExternalAddress(isIPv6); + byte[] externalListenHost = current != null ? current.getIP() : null; + int externalListenPort = current != null ? current.getPort() : getRequestedPort(isIPv6); + + if (_log.shouldLog(Log.INFO)) + _log.info("Change address? status = " + _reachabilityStatus + " diff = " + (_context.clock().now() - _reachabilityStatusLastUpdated) + " old = " + Addresses.toString(externalListenHost, externalListenPort) + " new = " + Addresses.toString(ourIP, ourPort)); - if ((fixedPort && externalListenPort > 0) || ourPort <= 0) - ourPort = externalListenPort; + if ((fixedPort && externalListenPort > 0) || ourPort <= 0) + ourPort = externalListenPort; - synchronized (this) { if (ourPort > 0 && !eq(externalListenHost, externalListenPort, ourIP, ourPort)) { // This prevents us from changing our IP when we are not firewalled @@ -1029,7 +1030,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority if (_log.shouldLog(Log.INFO)) _log.info("Same address as the current one"); } - } + } if (fireTest) { // always false, commented out above @@ -1087,7 +1088,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority _context.router().saveConfig(changes, null); } // deadlock thru here ticket #1699 - _context.router().rebuildRouterInfo(); + // this causes duplicate publish, REA() call above calls rebuildRouterInfo + //_context.router().rebuildRouterInfo(); _testEvent.forceRunImmediately(isIPv6); } return updated;