* Tunnels:
- Don't use peers < 0.7.9 for tunnels due to the old message corruption bugs - Javadoc - Cleanups
This commit is contained in:
@ -24,7 +24,7 @@ public class BuildMessageProcessor {
|
||||
|
||||
public BuildMessageProcessor(I2PAppContext ctx) {
|
||||
_filter = new DecayingHashSet(ctx, 60*1000, 32, "TunnelBMP");
|
||||
ctx.statManager().createRateStat("tunnel.buildRequestDup", "How frequently we get dup build request messages", "Tunnels", new long[] { 60*1000, 10*60*1000 });
|
||||
ctx.statManager().createRateStat("tunnel.buildRequestDup", "How frequently we get dup build request messages", "Tunnels", new long[] { 60*60*1000 });
|
||||
}
|
||||
/**
|
||||
* Decrypt the record targetting us, encrypting all of the other records with the included
|
||||
|
@ -15,17 +15,19 @@ import net.i2p.util.Log;
|
||||
*
|
||||
*/
|
||||
public class InboundEndpointProcessor {
|
||||
private RouterContext _context;
|
||||
private Log _log;
|
||||
private TunnelCreatorConfig _config;
|
||||
private IVValidator _validator;
|
||||
private final RouterContext _context;
|
||||
private final Log _log;
|
||||
private final TunnelCreatorConfig _config;
|
||||
private final IVValidator _validator;
|
||||
|
||||
static final boolean USE_ENCRYPTION = HopProcessor.USE_ENCRYPTION;
|
||||
private static final ByteCache _cache = ByteCache.getInstance(128, HopProcessor.IV_LENGTH);
|
||||
|
||||
/** @deprecated unused */
|
||||
public InboundEndpointProcessor(RouterContext ctx, TunnelCreatorConfig cfg) {
|
||||
this(ctx, cfg, DummyValidator.getInstance());
|
||||
}
|
||||
|
||||
public InboundEndpointProcessor(RouterContext ctx, TunnelCreatorConfig cfg, IVValidator validator) {
|
||||
_context = ctx;
|
||||
_log = ctx.logManager().getLog(InboundEndpointProcessor.class);
|
||||
@ -84,6 +86,9 @@ public class InboundEndpointProcessor {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iteratively undo the crypto that the various layers in the tunnel added.
|
||||
*/
|
||||
private void decrypt(RouterContext ctx, TunnelCreatorConfig cfg, byte iv[], byte orig[], int offset, int length) {
|
||||
Log log = ctx.logManager().getLog(OutboundGatewayProcessor.class);
|
||||
ByteArray ba = _cache.acquire();
|
||||
|
@ -14,9 +14,9 @@ import net.i2p.util.Log;
|
||||
*
|
||||
*/
|
||||
public class OutboundGatewayProcessor {
|
||||
private I2PAppContext _context;
|
||||
private Log _log;
|
||||
private TunnelCreatorConfig _config;
|
||||
private final I2PAppContext _context;
|
||||
private final Log _log;
|
||||
private final TunnelCreatorConfig _config;
|
||||
|
||||
static final boolean USE_ENCRYPTION = HopProcessor.USE_ENCRYPTION;
|
||||
private static final ByteCache _cache = ByteCache.getInstance(128, HopProcessor.IV_LENGTH);
|
||||
@ -54,10 +54,8 @@ public class OutboundGatewayProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo the crypto that the various layers in the tunnel added. This is used
|
||||
* by both the outbound gateway (preemptively undoing the crypto peers will add)
|
||||
* and by the inbound endpoint.
|
||||
*
|
||||
* Iteratively undo the crypto that the various layers in the tunnel added. This is used
|
||||
* by the outbound gateway (preemptively undoing the crypto peers will add).
|
||||
*/
|
||||
private void decrypt(I2PAppContext ctx, TunnelCreatorConfig cfg, byte iv[], byte orig[], int offset, int length) {
|
||||
Log log = ctx.logManager().getLog(OutboundGatewayProcessor.class);
|
||||
@ -73,6 +71,11 @@ public class OutboundGatewayProcessor {
|
||||
_cache.release(ba);
|
||||
}
|
||||
|
||||
/**
|
||||
* Undo the crypto for a single hop. This is used
|
||||
* by both the outbound gateway (preemptively undoing the crypto peers will add)
|
||||
* and by the inbound endpoint.
|
||||
*/
|
||||
static void decrypt(I2PAppContext ctx, byte iv[], byte orig[], int offset, int length, byte cur[], HopConfig config) {
|
||||
// update the IV for the previous (next?) hop
|
||||
ctx.aes().decryptBlock(orig, offset, config.getIVKey(), orig, offset);
|
||||
|
@ -60,7 +60,6 @@ public class TunnelGateway {
|
||||
_preprocessor = preprocessor;
|
||||
_sender = sender;
|
||||
_receiver = receiver;
|
||||
_messagesSent = 0;
|
||||
_flushFrequency = 500;
|
||||
_delayedFlush = new DelayedFlush();
|
||||
_lastFlush = _context.clock().now();
|
||||
@ -128,8 +127,8 @@ public class TunnelGateway {
|
||||
FlushTimer.getInstance().addEvent(_delayedFlush, delayAmount);
|
||||
}
|
||||
_context.statManager().addRateData("tunnel.lockedGatewayAdd", afterAdded-beforeLock, remaining);
|
||||
long complete = System.currentTimeMillis();
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
if (_log.shouldLog(Log.DEBUG)) {
|
||||
long complete = System.currentTimeMillis();
|
||||
_log.debug("Time to add the message " + msg.getUniqueId() + ": " + (complete-startAdd)
|
||||
+ " delayed? " + delayedFlush + " remaining: " + remaining
|
||||
+ " prepare: " + (beforeLock-startAdd)
|
||||
@ -137,6 +136,7 @@ public class TunnelGateway {
|
||||
+ " preprocess: " + (afterPreprocess-afterAdded)
|
||||
+ " expire: " + (afterExpire-afterPreprocess)
|
||||
+ " queue flush: " + (complete-afterExpire));
|
||||
}
|
||||
}
|
||||
|
||||
public int getMessagesSent() { return _messagesSent; }
|
||||
@ -202,10 +202,7 @@ public class TunnelGateway {
|
||||
_messageId = message.getUniqueId();
|
||||
_expiration = message.getMessageExpiration();
|
||||
_remaining = message.toByteArray();
|
||||
_offset = 0;
|
||||
_fragmentNumber = 0;
|
||||
_created = now;
|
||||
_messageIds = null;
|
||||
}
|
||||
/** may be null */
|
||||
public Hash getToRouter() { return _toRouter; }
|
||||
|
@ -5,6 +5,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.TunnelPoolSettings;
|
||||
|
||||
@ -14,7 +15,7 @@ import net.i2p.router.TunnelPoolSettings;
|
||||
*
|
||||
*/
|
||||
class ClientPeerSelector extends TunnelPeerSelector {
|
||||
public List selectPeers(RouterContext ctx, TunnelPoolSettings settings) {
|
||||
public List<Hash> selectPeers(RouterContext ctx, TunnelPoolSettings settings) {
|
||||
int length = getLength(ctx, settings);
|
||||
if (length < 0)
|
||||
return null;
|
||||
@ -31,7 +32,7 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
||||
ctx.profileOrganizer().selectFastPeers(length, exclude, matches, settings.getIPRestriction());
|
||||
|
||||
matches.remove(ctx.routerHash());
|
||||
ArrayList rv = new ArrayList(matches);
|
||||
ArrayList<Hash> rv = new ArrayList(matches);
|
||||
if (rv.size() > 1)
|
||||
orderPeers(rv, settings.getRandomKey());
|
||||
if (settings.isInbound())
|
||||
|
@ -5,6 +5,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.TunnelPoolSettings;
|
||||
import net.i2p.stat.Rate;
|
||||
@ -17,7 +18,7 @@ import net.i2p.util.Log;
|
||||
*
|
||||
*/
|
||||
class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
public List selectPeers(RouterContext ctx, TunnelPoolSettings settings) {
|
||||
public List<Hash> selectPeers(RouterContext ctx, TunnelPoolSettings settings) {
|
||||
Log l = ctx.logManager().getLog(getClass());
|
||||
int length = getLength(ctx, settings);
|
||||
if (length < 0) {
|
||||
@ -33,7 +34,7 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
return rv;
|
||||
}
|
||||
|
||||
Set exclude = getExclude(ctx, settings.isInbound(), settings.isExploratory());
|
||||
Set<Hash> exclude = getExclude(ctx, settings.isInbound(), settings.isExploratory());
|
||||
exclude.add(ctx.routerHash());
|
||||
// Don't use ff peers for exploratory tunnels to lessen exposure to netDb searches and stores
|
||||
// Hmm if they don't get explored they don't get a speed/capacity rating
|
||||
@ -56,7 +57,7 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
l.debug("profileOrganizer.selectNotFailing(" + length + ") found " + matches);
|
||||
|
||||
matches.remove(ctx.routerHash());
|
||||
ArrayList rv = new ArrayList(matches);
|
||||
ArrayList<Hash> rv = new ArrayList(matches);
|
||||
if (rv.size() > 1)
|
||||
orderPeers(rv, settings.getRandomKey());
|
||||
if (settings.isInbound())
|
||||
@ -67,7 +68,7 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
}
|
||||
|
||||
private static final int MIN_NONFAILING_PCT = 25;
|
||||
private boolean shouldPickHighCap(RouterContext ctx) {
|
||||
private static boolean shouldPickHighCap(RouterContext ctx) {
|
||||
if (Boolean.valueOf(ctx.getProperty("router.exploreHighCapacity", "false")).booleanValue())
|
||||
return true;
|
||||
// no need to explore too wildly at first
|
||||
@ -86,9 +87,9 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
failPct = 100 - MIN_NONFAILING_PCT;
|
||||
} else {
|
||||
failPct = getExploratoryFailPercentage(ctx);
|
||||
Log l = ctx.logManager().getLog(getClass());
|
||||
if (l.shouldLog(Log.DEBUG))
|
||||
l.debug("Normalized Fail pct: " + failPct);
|
||||
//Log l = ctx.logManager().getLog(getClass());
|
||||
//if (l.shouldLog(Log.DEBUG))
|
||||
// l.debug("Normalized Fail pct: " + failPct);
|
||||
// always try a little, this helps keep the failPct stat accurate too
|
||||
if (failPct > 100 - MIN_NONFAILING_PCT)
|
||||
failPct = 100 - MIN_NONFAILING_PCT;
|
||||
@ -96,21 +97,23 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
return (failPct >= ctx.random().nextInt(100));
|
||||
}
|
||||
|
||||
// We should really use the difference between the exploratory fail rate
|
||||
// and the high capacity fail rate - but we don't have a stat for high cap,
|
||||
// so use the fast (== client) fail rate, it should be close
|
||||
// if the expl. and client tunnel lengths aren't too different.
|
||||
// So calculate the difference between the exploratory fail rate
|
||||
// and the client fail rate, normalized to 100:
|
||||
// 100 * ((Efail - Cfail) / (100 - Cfail))
|
||||
// Even this isn't the "true" rate for the NonFailingPeers pool, since we
|
||||
// are often building exploratory tunnels using the HighCapacity pool.
|
||||
private int getExploratoryFailPercentage(RouterContext ctx) {
|
||||
/**
|
||||
* We should really use the difference between the exploratory fail rate
|
||||
* and the high capacity fail rate - but we don't have a stat for high cap,
|
||||
* so use the fast (== client) fail rate, it should be close
|
||||
* if the expl. and client tunnel lengths aren't too different.
|
||||
* So calculate the difference between the exploratory fail rate
|
||||
* and the client fail rate, normalized to 100:
|
||||
* 100 * ((Efail - Cfail) / (100 - Cfail))
|
||||
* Even this isn't the "true" rate for the NonFailingPeers pool, since we
|
||||
* are often building exploratory tunnels using the HighCapacity pool.
|
||||
*/
|
||||
private static int getExploratoryFailPercentage(RouterContext ctx) {
|
||||
int c = getFailPercentage(ctx, "Client");
|
||||
int e = getFailPercentage(ctx, "Exploratory");
|
||||
Log l = ctx.logManager().getLog(getClass());
|
||||
if (l.shouldLog(Log.DEBUG))
|
||||
l.debug("Client, Expl. Fail pct: " + c + ", " + e);
|
||||
//Log l = ctx.logManager().getLog(getClass());
|
||||
//if (l.shouldLog(Log.DEBUG))
|
||||
// l.debug("Client, Expl. Fail pct: " + c + ", " + e);
|
||||
if (e <= c || e <= 25) // doing very well (unlikely)
|
||||
return 0;
|
||||
if (c >= 90) // doing very badly
|
||||
@ -118,7 +121,7 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
return (100 * (e-c)) / (100-c);
|
||||
}
|
||||
|
||||
private int getFailPercentage(RouterContext ctx, String t) {
|
||||
private static int getFailPercentage(RouterContext ctx, String t) {
|
||||
String pfx = "tunnel.build" + t;
|
||||
int timeout = getEvents(ctx, pfx + "Expire", 10*60*1000);
|
||||
int reject = getEvents(ctx, pfx + "Reject", 10*60*1000);
|
||||
@ -129,8 +132,8 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
return (int)(100 * pct);
|
||||
}
|
||||
|
||||
// Use current + last to get more recent and smoother data
|
||||
private int getEvents(RouterContext ctx, String stat, long period) {
|
||||
/** Use current + last to get more recent and smoother data */
|
||||
private static int getEvents(RouterContext ctx, String stat, long period) {
|
||||
RateStat rs = ctx.statManager().getRate(stat);
|
||||
if (rs == null)
|
||||
return 0;
|
||||
|
@ -12,7 +12,7 @@ import net.i2p.util.Log;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class PooledTunnelCreatorConfig extends TunnelCreatorConfig {
|
||||
class PooledTunnelCreatorConfig extends TunnelCreatorConfig {
|
||||
private TunnelPool _pool;
|
||||
private TestJob _testJob;
|
||||
// private Job _expireJob;
|
||||
|
@ -21,10 +21,13 @@ import net.i2p.router.TunnelPoolSettings;
|
||||
import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
|
||||
import net.i2p.router.networkdb.kademlia.HashDistance;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.VersionComparator;
|
||||
|
||||
/**
|
||||
* Coordinate the selection of peers to go into a tunnel for one particular
|
||||
* pool.
|
||||
*
|
||||
* Todo: there's nothing non-static in here
|
||||
*/
|
||||
public abstract class TunnelPeerSelector {
|
||||
/**
|
||||
@ -36,7 +39,7 @@ public abstract class TunnelPeerSelector {
|
||||
* to build through, and the settings reject 0 hop tunnels, this will
|
||||
* return null.
|
||||
*/
|
||||
public abstract List selectPeers(RouterContext ctx, TunnelPoolSettings settings);
|
||||
public abstract List<Hash> selectPeers(RouterContext ctx, TunnelPoolSettings settings);
|
||||
|
||||
protected int getLength(RouterContext ctx, TunnelPoolSettings settings) {
|
||||
int length = settings.getLength();
|
||||
@ -79,6 +82,11 @@ public abstract class TunnelPeerSelector {
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* For debugging, also possibly for restricted routes?
|
||||
* Needs analysis and testing
|
||||
* @return should always be false
|
||||
*/
|
||||
protected boolean shouldSelectExplicit(TunnelPoolSettings settings) {
|
||||
if (settings.isExploratory()) return false;
|
||||
Properties opts = settings.getUnknownOptions();
|
||||
@ -92,7 +100,12 @@ public abstract class TunnelPeerSelector {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected List selectExplicit(RouterContext ctx, TunnelPoolSettings settings, int length) {
|
||||
/**
|
||||
* For debugging, also possibly for restricted routes?
|
||||
* Needs analysis and testing
|
||||
* @return should always be false
|
||||
*/
|
||||
protected List<Hash> selectExplicit(RouterContext ctx, TunnelPoolSettings settings, int length) {
|
||||
String peers = null;
|
||||
Properties opts = settings.getUnknownOptions();
|
||||
if (opts != null)
|
||||
@ -102,7 +115,7 @@ public abstract class TunnelPeerSelector {
|
||||
peers = I2PAppContext.getGlobalContext().getProperty("explicitPeers");
|
||||
|
||||
Log log = ctx.logManager().getLog(ClientPeerSelector.class);
|
||||
List rv = new ArrayList();
|
||||
List<Hash> rv = new ArrayList();
|
||||
StringTokenizer tok = new StringTokenizer(peers, ",");
|
||||
while (tok.hasMoreTokens()) {
|
||||
String peerStr = tok.nextToken();
|
||||
@ -156,7 +169,7 @@ public abstract class TunnelPeerSelector {
|
||||
/**
|
||||
* Pick peers that we want to avoid
|
||||
*/
|
||||
public Set getExclude(RouterContext ctx, boolean isInbound, boolean isExploratory) {
|
||||
public Set<Hash> getExclude(RouterContext ctx, boolean isInbound, boolean isExploratory) {
|
||||
// we may want to update this to skip 'hidden' or 'unreachable' peers, but that
|
||||
// isn't safe, since they may publish one set of routerInfo to us and another to
|
||||
// other peers. the defaults for filterUnreachable has always been to return false,
|
||||
@ -175,11 +188,12 @@ public abstract class TunnelPeerSelector {
|
||||
//
|
||||
// Defaults changed to true for inbound only in filterUnreachable below.
|
||||
|
||||
Set peers = new HashSet(1);
|
||||
Set<Hash> peers = new HashSet(1);
|
||||
peers.addAll(ctx.profileOrganizer().selectPeersRecentlyRejecting());
|
||||
peers.addAll(ctx.tunnelManager().selectPeersInTooManyTunnels());
|
||||
// if (false && filterUnreachable(ctx, isInbound, isExploratory)) {
|
||||
if (filterUnreachable(ctx, isInbound, isExploratory)) {
|
||||
// NOTE: filterUnreachable returns true for inbound, false for outbound
|
||||
// This is the only use for getPeersByCapability? And the whole set of datastructures in PeerManager?
|
||||
List<Hash> caps = ctx.peerManager().getPeersByCapability(Router.CAPABILITY_UNREACHABLE);
|
||||
if (caps != null)
|
||||
@ -189,6 +203,7 @@ public abstract class TunnelPeerSelector {
|
||||
peers.addAll(caps);
|
||||
}
|
||||
if (filterSlow(ctx, isInbound, isExploratory)) {
|
||||
// NOTE: filterSlow always returns true
|
||||
Log log = ctx.logManager().getLog(TunnelPeerSelector.class);
|
||||
char excl[] = getExcludeCaps(ctx);
|
||||
if (excl != null) {
|
||||
@ -301,6 +316,7 @@ public abstract class TunnelPeerSelector {
|
||||
return peers;
|
||||
}
|
||||
|
||||
/** warning, this is also called by ProfileOrganizer.isSelectable() */
|
||||
public static boolean shouldExclude(RouterContext ctx, RouterInfo peer) {
|
||||
Log log = ctx.logManager().getLog(TunnelPeerSelector.class);
|
||||
return shouldExclude(ctx, log, peer, getExcludeCaps(ctx));
|
||||
@ -318,6 +334,10 @@ public abstract class TunnelPeerSelector {
|
||||
}
|
||||
|
||||
private static final long DONT_EXCLUDE_PERIOD = 15*60*1000;
|
||||
/** 0.7.8 and earlier had major message corruption bugs */
|
||||
private static final String MIN_VERSION = "0.7.9";
|
||||
private static final VersionComparator _versionComparator = new VersionComparator();
|
||||
|
||||
private static boolean shouldExclude(RouterContext ctx, Log log, RouterInfo peer, char excl[]) {
|
||||
String cap = peer.getCapabilities();
|
||||
if (cap == null) {
|
||||
@ -340,6 +360,13 @@ public abstract class TunnelPeerSelector {
|
||||
// otherwise, it contains flags we aren't trying to focus on,
|
||||
// so don't exclude it based on published capacity
|
||||
|
||||
// minimum version check
|
||||
String v = peer.getOption("router.version");
|
||||
if (v == null || _versionComparator.compare(v, MIN_VERSION) < 0)
|
||||
return true;
|
||||
|
||||
// uptime is always spoofed to 90m, so just remove all this
|
||||
/******
|
||||
String val = peer.getOption("stat_uptime");
|
||||
if (val != null) {
|
||||
long uptimeMs = 0;
|
||||
@ -390,6 +417,8 @@ public abstract class TunnelPeerSelector {
|
||||
// not publishing an uptime, so exclude it
|
||||
return true;
|
||||
}
|
||||
******/
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final String PROP_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = "router.outboundExploratoryExcludeUnreachable";
|
||||
@ -403,6 +432,10 @@ public abstract class TunnelPeerSelector {
|
||||
private static final String DEFAULT_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = "true";
|
||||
private static final String DEFAULT_INBOUND_CLIENT_EXCLUDE_UNREACHABLE = "true";
|
||||
|
||||
/**
|
||||
* do we want to skip peers who haven't been up for long?
|
||||
* @return true for inbound, false for outbound, unless configured otherwise
|
||||
*/
|
||||
protected boolean filterUnreachable(RouterContext ctx, boolean isInbound, boolean isExploratory) {
|
||||
boolean def = false;
|
||||
String val = null;
|
||||
@ -429,6 +462,10 @@ public abstract class TunnelPeerSelector {
|
||||
private static final String PROP_INBOUND_EXPLORATORY_EXCLUDE_SLOW = "router.inboundExploratoryExcludeSlow";
|
||||
private static final String PROP_INBOUND_CLIENT_EXCLUDE_SLOW = "router.inboundClientExcludeSlow";
|
||||
|
||||
/**
|
||||
* do we want to skip peers that are slow?
|
||||
* @return true unless configured otherwise
|
||||
*/
|
||||
protected boolean filterSlow(RouterContext ctx, boolean isInbound, boolean isExploratory) {
|
||||
boolean def = true;
|
||||
String val = null;
|
||||
@ -454,7 +491,10 @@ public abstract class TunnelPeerSelector {
|
||||
private static final String PROP_INBOUND_EXPLORATORY_EXCLUDE_UPTIME = "router.inboundExploratoryExcludeUptime";
|
||||
private static final String PROP_INBOUND_CLIENT_EXCLUDE_UPTIME = "router.inboundClientExcludeUptime";
|
||||
|
||||
/** do we want to skip peers who haven't been up for long? */
|
||||
/**
|
||||
* do we want to skip peers who haven't been up for long?
|
||||
* @return true unless configured otherwise
|
||||
*/
|
||||
protected boolean filterUptime(RouterContext ctx, boolean isInbound, boolean isExploratory) {
|
||||
boolean def = true;
|
||||
String val = null;
|
||||
|
Reference in New Issue
Block a user