NetDb: Search for new leaseset before expiration

Reduce expiration for router infos with introducers
More negative cache checks
Log tweaks
SSU: Switch introducers less often
This commit is contained in:
zzz
2016-03-01 13:30:30 +00:00
parent ffa4d6580d
commit 50d038af5d
8 changed files with 86 additions and 28 deletions

View File

@ -1,3 +1,12 @@
2016-03-01 zzz
* i2psnark: Fix handling of HAVE messages received before metainfo
* i2ptunnel: Don't default to a private key file that exists (ticket #1628)
* NetDb:
- Search for new leaseset before expiration;
- Reduce expiration for router infos with introducers
- Add missing reseed cert
* SSU: Switch introducers less often
2016-02-26 zzz 2016-02-26 zzz
* Console: * Console:
- Add X-Content-Type-Options header everywhere (ticket #1763) - Add X-Content-Type-Options header everywhere (ticket #1763)
@ -8,6 +17,8 @@
- Add QR code generation - Add QR code generation
* Router: Log full path to wrapper.log when dumping threads * Router: Log full path to wrapper.log when dumping threads
* Transports: Increase connection limits for class N and higher * Transports: Increase connection limits for class N and higher
* Utils: Add main classes to i2p.jar and router.jar
for simple command line access to utilities
2016-02-22 zzz 2016-02-22 zzz
* Console: Improve news CSS (ticket #1710) * Console: Improve news CSS (ticket #1710)

View File

@ -52,6 +52,16 @@ public abstract class NetworkDatabaseFacade implements Service {
public abstract LeaseSet lookupLeaseSetLocally(Hash key); public abstract LeaseSet lookupLeaseSetLocally(Hash key);
public abstract void lookupRouterInfo(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs); public abstract void lookupRouterInfo(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs);
public abstract RouterInfo lookupRouterInfoLocally(Hash key); public abstract RouterInfo lookupRouterInfoLocally(Hash key);
/**
* Unconditionally lookup using the client's tunnels.
* No success or failed jobs, no local lookup, no checks.
* Use this to refresh a leaseset before expiration.
*
* @param fromLocalDest use these tunnels for the lookup, or null for exploratory
* @since 0.9.25
*/
public abstract void lookupLeaseSetRemotely(Hash key, Hash fromLocalDest);
/** /**
* Lookup using the client's tunnels * Lookup using the client's tunnels

View File

@ -18,10 +18,10 @@ public class RouterVersion {
/** deprecated */ /** deprecated */
public final static String ID = "Monotone"; public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION; public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 9; public final static long BUILD = 10;
/** for example "-test" */ /** for example "-test" */
public final static String EXTRA = ""; public final static String EXTRA = "-rc";
public final static String FULL_VERSION = VERSION + "-" + BUILD + EXTRA; public final static String FULL_VERSION = VERSION + "-" + BUILD + EXTRA;
public static void main(String args[]) { public static void main(String args[]) {
System.out.println("I2P Router version: " + FULL_VERSION); System.out.println("I2P Router version: " + FULL_VERSION);

View File

@ -43,6 +43,7 @@ public class DummyNetworkDatabaseFacade extends NetworkDatabaseFacade {
public void lookupLeaseSet(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs) {} public void lookupLeaseSet(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs) {}
public void lookupLeaseSet(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs, Hash fromLocalDest) {} public void lookupLeaseSet(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs, Hash fromLocalDest) {}
public LeaseSet lookupLeaseSetLocally(Hash key) { return null; } public LeaseSet lookupLeaseSetLocally(Hash key) { return null; }
public void lookupLeaseSetRemotely(Hash key, Hash fromLocalDest) {}
public void lookupDestination(Hash key, Job onFinishedJob, long timeoutMs, Hash fromLocalDest) {} public void lookupDestination(Hash key, Job onFinishedJob, long timeoutMs, Hash fromLocalDest) {}

View File

@ -281,6 +281,19 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
//getContext().statManager().addRateData("client.leaseSetFoundLocally", 1); //getContext().statManager().addRateData("client.leaseSetFoundLocally", 1);
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug(getJobId() + ": Send outbound client message - leaseSet found locally for " + _toString); _log.debug(getJobId() + ": Send outbound client message - leaseSet found locally for " + _toString);
if (!_leaseSet.isCurrent(Router.CLOCK_FUDGE_FACTOR / 4)) {
// If it's about to expire, refetch in the background, we'll
// probably need it again. This will prevent stalls later.
// We don't know if the other end is actually publishing his LS, so this could be a waste of time.
// When we move to LS2, we will have a bit that tells us if it is published.
if (_log.shouldWarn()) {
long exp = now - _leaseSet.getLatestLeaseDate();
_log.warn(getJobId() + ": leaseSet expired " + DataHelper.formatDuration(exp) + " ago, firing search: " + _leaseSet.getHash().toBase32());
}
getContext().netDb().lookupLeaseSetRemotely(_leaseSet.getHash(), _from.calculateHash());
}
success.runJob(); success.runJob();
} else { } else {
_leaseSetLookupBegin = getContext().clock().now(); _leaseSetLookupBegin = getContext().clock().now();

View File

@ -343,7 +343,7 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
//if (true) return super.search(key, onFindJob, onFailedLookupJob, timeoutMs, isLease); //if (true) return super.search(key, onFindJob, onFailedLookupJob, timeoutMs, isLease);
if (key == null) throw new IllegalArgumentException("searchin for nothin, eh?"); if (key == null) throw new IllegalArgumentException("searchin for nothin, eh?");
boolean isNew = false; boolean isNew = false;
FloodSearchJob searchJob = null; FloodSearchJob searchJob;
synchronized (_activeFloodQueries) { synchronized (_activeFloodQueries) {
searchJob = _activeFloodQueries.get(key); searchJob = _activeFloodQueries.get(key);
if (searchJob == null) { if (searchJob == null) {

View File

@ -133,6 +133,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
private final static long ROUTER_INFO_EXPIRATION_MIN = 90*60*1000l; private final static long ROUTER_INFO_EXPIRATION_MIN = 90*60*1000l;
private final static long ROUTER_INFO_EXPIRATION_SHORT = 75*60*1000l; private final static long ROUTER_INFO_EXPIRATION_SHORT = 75*60*1000l;
private final static long ROUTER_INFO_EXPIRATION_FLOODFILL = 60*60*1000l; private final static long ROUTER_INFO_EXPIRATION_FLOODFILL = 60*60*1000l;
private final static long ROUTER_INFO_EXPIRATION_INTRODUCED = 45*60*1000l;
private final static long EXPLORE_JOB_DELAY = 10*60*1000l; private final static long EXPLORE_JOB_DELAY = 10*60*1000l;
@ -493,7 +494,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
/** /**
* Lookup using exploratory tunnels. * Lookup using exploratory tunnels.
* Use lookupDestination() if you don't need the LS or need it validated. * Use lookupDestination() if you don't need the LS or don't need it validated.
*/ */
public void lookupLeaseSet(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs) { public void lookupLeaseSet(Hash key, Job onFindJob, Job onFailedLookupJob, long timeoutMs) {
lookupLeaseSet(key, onFindJob, onFailedLookupJob, timeoutMs, null); lookupLeaseSet(key, onFindJob, onFailedLookupJob, timeoutMs, null);
@ -501,7 +502,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
/** /**
* Lookup using the client's tunnels * Lookup using the client's tunnels
* Use lookupDestination() if you don't need the LS or need it validated. * Use lookupDestination() if you don't need the LS or don't need it validated.
* *
* @param fromLocalDest use these tunnels for the lookup, or null for exploratory * @param fromLocalDest use these tunnels for the lookup, or null for exploratory
* @since 0.9.10 * @since 0.9.10
@ -511,26 +512,39 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
if (!_initialized) return; if (!_initialized) return;
LeaseSet ls = lookupLeaseSetLocally(key); LeaseSet ls = lookupLeaseSetLocally(key);
if (ls != null) { if (ls != null) {
if (_log.shouldLog(Log.DEBUG)) //if (_log.shouldLog(Log.DEBUG))
_log.debug("leaseSet found locally, firing " + onFindJob); // _log.debug("leaseSet found locally, firing " + onFindJob);
if (onFindJob != null) if (onFindJob != null)
_context.jobQueue().addJob(onFindJob); _context.jobQueue().addJob(onFindJob);
} else if (isNegativeCached(key)) { } else if (isNegativeCached(key)) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Negative cached, not searching: " + key); _log.warn("Negative cached, not searching LS: " + key);
if (onFailedLookupJob != null) if (onFailedLookupJob != null)
_context.jobQueue().addJob(onFailedLookupJob); _context.jobQueue().addJob(onFailedLookupJob);
} else { } else {
if (_log.shouldLog(Log.DEBUG)) //if (_log.shouldLog(Log.DEBUG))
_log.debug("leaseSet not found locally, running search"); // _log.debug("leaseSet not found locally, running search");
search(key, onFindJob, onFailedLookupJob, timeoutMs, true, fromLocalDest); search(key, onFindJob, onFailedLookupJob, timeoutMs, true, fromLocalDest);
} }
if (_log.shouldLog(Log.DEBUG)) //if (_log.shouldLog(Log.DEBUG))
_log.debug("after lookupLeaseSet"); // _log.debug("after lookupLeaseSet");
} }
/** /**
* Use lookupDestination() if you don't need the LS or need it validated. * Unconditionally lookup using the client's tunnels.
* No success or failed jobs, no local lookup, no checks.
* Use this to refresh a leaseset before expiration.
*
* @param fromLocalDest use these tunnels for the lookup, or null for exploratory
* @since 0.9.25
*/
public void lookupLeaseSetRemotely(Hash key, Hash fromLocalDest) {
if (!_initialized) return;
search(key, null, null, 20*1000, true, fromLocalDest);
}
/**
* Use lookupDestination() if you don't need the LS or don't need it validated.
*/ */
public LeaseSet lookupLeaseSetLocally(Hash key) { public LeaseSet lookupLeaseSetLocally(Hash key) {
if (!_initialized) return null; if (!_initialized) return null;
@ -571,6 +585,9 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
Destination d = lookupDestinationLocally(key); Destination d = lookupDestinationLocally(key);
if (d != null) { if (d != null) {
_context.jobQueue().addJob(onFinishedJob); _context.jobQueue().addJob(onFinishedJob);
} else if (isNegativeCached(key)) {
if (_log.shouldLog(Log.WARN))
_log.warn("Negative cached, not searching dest: " + key);
} else { } else {
search(key, onFinishedJob, onFinishedJob, timeoutMs, true, fromLocalDest); search(key, onFinishedJob, onFinishedJob, timeoutMs, true, fromLocalDest);
} }
@ -605,6 +622,9 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
} else if (_context.banlist().isBanlistedForever(key)) { } else if (_context.banlist().isBanlistedForever(key)) {
if (onFailedLookupJob != null) if (onFailedLookupJob != null)
_context.jobQueue().addJob(onFailedLookupJob); _context.jobQueue().addJob(onFailedLookupJob);
} else if (isNegativeCached(key)) {
if (_log.shouldLog(Log.WARN))
_log.warn("Negative cached, not searching RI: " + key);
} else { } else {
search(key, onFindJob, onFailedLookupJob, timeoutMs, false); search(key, onFindJob, onFailedLookupJob, timeoutMs, false);
} }
@ -957,25 +977,28 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
+ new Date(routerInfo.getPublished()) + "]", new Exception()); + new Date(routerInfo.getPublished()) + "]", new Exception());
return "Peer published " + DataHelper.formatDuration(age) + " in the future?!"; return "Peer published " + DataHelper.formatDuration(age) + " in the future?!";
} }
if (!routerInfo.isCurrent(ROUTER_INFO_EXPIRATION_INTRODUCED)) {
if (routerInfo.getAddresses().isEmpty())
return "Old peer with no addresses";
// This should cover the introducers case below too
// And even better, catches the case where the router is unreachable but knows no introducers
if (routerInfo.getCapabilities().indexOf(Router.CAPABILITY_UNREACHABLE) >= 0)
return "Old peer and thinks it is unreachable";
// FIXME check all SSU addresses, not just first
RouterAddress ra = routerInfo.getTargetAddress("SSU");
if (ra != null) {
// Introducers change often, introducee will ping introducer for 2 hours
if (ra.getOption("ihost0") != null)
return "Old peer with SSU Introducers";
}
}
if (upLongEnough && (routerInfo.getPublished() < now - 2*24*60*60*1000l) ) { if (upLongEnough && (routerInfo.getPublished() < now - 2*24*60*60*1000l) ) {
long age = _context.clock().now() - routerInfo.getPublished(); long age = _context.clock().now() - routerInfo.getPublished();
return "Peer published " + DataHelper.formatDuration(age) + " ago"; return "Peer published " + DataHelper.formatDuration(age) + " ago";
} }
if (upLongEnough && !routerInfo.isCurrent(ROUTER_INFO_EXPIRATION_SHORT)) { if (upLongEnough && !routerInfo.isCurrent(ROUTER_INFO_EXPIRATION_SHORT)) {
if (routerInfo.getAddresses().isEmpty()) if (routerInfo.getTargetAddress("NTCP") == null)
return "Peer published > 75m ago with no addresses"; return "Peer published > 75m ago, SSU only without introducers";
// This should cover the introducers case below too
// And even better, catches the case where the router is unreachable but knows no introducers
if (routerInfo.getCapabilities().indexOf(Router.CAPABILITY_UNREACHABLE) >= 0)
return "Peer published > 75m ago and thinks it is unreachable";
RouterAddress ra = routerInfo.getTargetAddress("SSU");
if (ra != null) {
// Introducers change often, introducee will ping introducer for 2 hours
if (ra.getOption("ihost0") != null)
return "Peer published > 75m ago with SSU Introducers";
if (routerInfo.getTargetAddress("NTCP") == null)
return "Peer published > 75m ago, SSU only without introducers";
}
} }
return null; return null;
} }

View File

@ -1500,7 +1500,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
long sinceSelected = _context.clock().now() - _introducersSelectedOn; long sinceSelected = _context.clock().now() - _introducersSelectedOn;
if (valid >= PUBLIC_RELAY_COUNT) { if (valid >= PUBLIC_RELAY_COUNT) {
// try to shift 'em around every 10 minutes or so // try to shift 'em around every 10 minutes or so
if (sinceSelected > 10*60*1000) { if (sinceSelected > 17*60*1000) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Our introducers are valid, but haven't changed in " + DataHelper.formatDuration(sinceSelected) + ", so lets rechoose"); _log.warn("Our introducers are valid, but haven't changed in " + DataHelper.formatDuration(sinceSelected) + ", so lets rechoose");
return true; return true;