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 71ce99fc4bcc67496c6765e26fe0471ded067c8f..16ba17cac8fa8f57e5c47963d600ac882887869e 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java @@ -28,6 +28,7 @@ import net.i2p.stat.RateStat; import net.i2p.util.ConcurrentHashSet; import net.i2p.util.Log; import net.i2p.util.RandomSource; +import net.i2p.util.SimpleTimer2; import net.i2p.util.SystemVersion; /** @@ -185,10 +186,42 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad // (unless maybe we used to have addresses? not worth it if (localRouterInfo.getAddresses().isEmpty()) return; - _log.info("Publishing our RI"); - // Don't delay, helps IB tunnel builds - //if (_context.router().getUptime() > PUBLISH_JOB_DELAY) + if (_context.router().getUptime() > PUBLISH_JOB_DELAY) { + _log.info("Publishing our RI"); sendStore(localRouterInfo.getIdentity().calculateHash(), localRouterInfo, null, null, PUBLISH_TIMEOUT, null); + } else { + // transports may rapidly force republishes at startup as they collect addresses + // and reachability status from UPnP, peers, and peer testing + // so "debounce" them by delaying slightly + _log.info("Delay publishing our RI"); + DelayedPublish dp = new DelayedPublish(localRouterInfo); + dp.schedule(3*1000); + } + } + + /** + * Don't actually publish unless the RI didn't change during the delay + * @since 0.9.65 + */ + private class DelayedPublish extends SimpleTimer2.TimedEvent { + private final RouterInfo localRouterInfo; + public DelayedPublish(RouterInfo local) { + super(_context.simpleTimer2()); + localRouterInfo = local; + } + public void timeReached() { + RouterInfo latest = _context.router().getRouterInfo(); + // clock may skew during startup so we do an exact == check, not <= + if (latest.getDate() == localRouterInfo.getDate()) { + if (_log.shouldWarn()) + _log.warn("Publishing our RI after delay: " + localRouterInfo); + sendStore(localRouterInfo.getIdentity().calculateHash(), localRouterInfo, null, null, PUBLISH_TIMEOUT, null); + } else { + // do nothing, there's another one of these right behind us + if (_log.shouldWarn()) + _log.warn("RI changed, not publishing old one: " + localRouterInfo); + } + } } /**