forked from I2P_Developers/i2p.i2p
Router: More peer selection fixes for hidden mode
Fix excludes after calling SANFP Pick connected OBEP when hidden and paired tunnel is zero-hop
This commit is contained in:
14
history.txt
14
history.txt
@ -1,5 +1,17 @@
|
|||||||
|
2018-03-11 zzz
|
||||||
|
* Router: More peer selection fixes for hidden mode
|
||||||
|
|
||||||
|
2018-03-10 zzz
|
||||||
|
* Console: Fix compression logic
|
||||||
|
* i2ptunnel: Strip server Date header
|
||||||
|
* NetDB: Wake up FloodfillMonitor when setting changes
|
||||||
|
* Router: Fix rekey after hidden config change
|
||||||
|
|
||||||
2018-03-09 zzz
|
2018-03-09 zzz
|
||||||
* Console: Enable compression (ticket #2157)
|
* Console:
|
||||||
|
- Enable compression (ticket #2157)
|
||||||
|
- Close output stream on redirect
|
||||||
|
- Add Accept-Ranges header
|
||||||
|
|
||||||
2018-03-08 zzz
|
2018-03-08 zzz
|
||||||
* Crypto: Generate non-CA cert for family
|
* Crypto: Generate non-CA cert for family
|
||||||
|
@ -18,7 +18,7 @@ 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 = 14;
|
public final static long BUILD = 15;
|
||||||
|
|
||||||
/** for example "-test" */
|
/** for example "-test" */
|
||||||
public final static String EXTRA = "";
|
public final static String EXTRA = "";
|
||||||
|
@ -182,6 +182,18 @@ public interface TunnelManagerFacade extends Service {
|
|||||||
/** for TunnelRenderer in router console */
|
/** for TunnelRenderer in router console */
|
||||||
public TunnelPool getOutboundExploratoryPool();
|
public TunnelPool getOutboundExploratoryPool();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return pool or null
|
||||||
|
* @since 0.9.34
|
||||||
|
*/
|
||||||
|
public TunnelPool getInboundPool(Hash client);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return pool or null
|
||||||
|
* @since 0.9.34
|
||||||
|
*/
|
||||||
|
public TunnelPool getOutboundPool(Hash client);
|
||||||
|
|
||||||
/** @since 0.8.13 */
|
/** @since 0.8.13 */
|
||||||
public void fail(Hash peer);
|
public void fail(Hash peer);
|
||||||
}
|
}
|
||||||
|
@ -75,4 +75,12 @@ public class DummyTunnelManagerFacade implements TunnelManagerFacade {
|
|||||||
public TunnelPool getInboundExploratoryPool() { return null; }
|
public TunnelPool getInboundExploratoryPool() { return null; }
|
||||||
public TunnelPool getOutboundExploratoryPool() { return null; }
|
public TunnelPool getOutboundExploratoryPool() { return null; }
|
||||||
public void fail(Hash peer) {}
|
public void fail(Hash peer) {}
|
||||||
|
|
||||||
|
public TunnelPool getInboundPool(Hash client) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TunnelPool getOutboundPool(Hash client) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -571,7 +571,7 @@ public class ProfileOrganizer {
|
|||||||
* Caution, this does NOT cascade further to non-connected peers, so it should only
|
* Caution, this does NOT cascade further to non-connected peers, so it should only
|
||||||
* be used when there is a good number of connected peers.
|
* be used when there is a good number of connected peers.
|
||||||
*
|
*
|
||||||
* @param exclude non-null
|
* @param exclude non-null, WARNING - side effect, all not-connected peers are added
|
||||||
* No mask parameter, to be fixed
|
* No mask parameter, to be fixed
|
||||||
*/
|
*/
|
||||||
public void selectActiveNotFailingPeers(int howMany, Set<Hash> exclude, Set<Hash> matches) {
|
public void selectActiveNotFailingPeers(int howMany, Set<Hash> exclude, Set<Hash> matches) {
|
||||||
|
@ -8,6 +8,8 @@ import java.util.Set;
|
|||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
import net.i2p.data.Hash;
|
import net.i2p.data.Hash;
|
||||||
import net.i2p.router.RouterContext;
|
import net.i2p.router.RouterContext;
|
||||||
|
import net.i2p.router.TunnelInfo;
|
||||||
|
import net.i2p.router.TunnelManagerFacade;
|
||||||
import net.i2p.router.TunnelPoolSettings;
|
import net.i2p.router.TunnelPoolSettings;
|
||||||
import static net.i2p.router.peermanager.ProfileOrganizer.Slice.*;
|
import static net.i2p.router.peermanager.ProfileOrganizer.Slice.*;
|
||||||
|
|
||||||
@ -52,6 +54,7 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
|||||||
boolean hidden = ctx.router().isHidden() ||
|
boolean hidden = ctx.router().isHidden() ||
|
||||||
ctx.router().getRouterInfo().getAddressCount() <= 0;
|
ctx.router().getRouterInfo().getAddressCount() <= 0;
|
||||||
boolean hiddenInbound = hidden && isInbound;
|
boolean hiddenInbound = hidden && isInbound;
|
||||||
|
boolean hiddenOutbound = hidden && !isInbound;
|
||||||
|
|
||||||
if (shouldSelectExplicit(settings))
|
if (shouldSelectExplicit(settings))
|
||||||
return selectExplicit(settings, length);
|
return selectExplicit(settings, length);
|
||||||
@ -65,8 +68,11 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
|||||||
if (moreExclude != null)
|
if (moreExclude != null)
|
||||||
exclude.addAll(moreExclude);
|
exclude.addAll(moreExclude);
|
||||||
}
|
}
|
||||||
if (hiddenInbound)
|
if (hiddenInbound) {
|
||||||
ctx.profileOrganizer().selectActiveNotFailingPeers(1, exclude, matches);
|
// SANFP adds all not-connected to exclude, so make a copy
|
||||||
|
Set<Hash> SANFPExclude = new HashSet<Hash>(exclude);
|
||||||
|
ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, matches);
|
||||||
|
}
|
||||||
if (matches.isEmpty()) {
|
if (matches.isEmpty()) {
|
||||||
// ANFP does not fall back to non-connected
|
// ANFP does not fall back to non-connected
|
||||||
ctx.profileOrganizer().selectFastPeers(length, exclude, matches, 0);
|
ctx.profileOrganizer().selectFastPeers(length, exclude, matches, 0);
|
||||||
@ -78,9 +84,10 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
|||||||
// For a 2-hop tunnel, the first hop comes from subtiers 0-1 and the last from subtiers 2-3.
|
// For a 2-hop tunnel, the first hop comes from subtiers 0-1 and the last from subtiers 2-3.
|
||||||
// For a longer tunnels, the first hop comes from subtier 0, the middle from subtiers 2-3, and the last from subtier 1.
|
// For a longer tunnels, the first hop comes from subtier 0, the middle from subtiers 2-3, and the last from subtier 1.
|
||||||
rv = new ArrayList<Hash>(length + 1);
|
rv = new ArrayList<Hash>(length + 1);
|
||||||
|
Hash randomKey = settings.getRandomKey();
|
||||||
// OBEP or IB last hop
|
// OBEP or IB last hop
|
||||||
// group 0 or 1 if two hops, otherwise group 0
|
// group 0 or 1 if two hops, otherwise group 0
|
||||||
Set<Hash> firstHopExclude;
|
Set<Hash> lastHopExclude;
|
||||||
if (isInbound) {
|
if (isInbound) {
|
||||||
// exclude existing OBEPs to get some diversity ?
|
// exclude existing OBEPs to get some diversity ?
|
||||||
// closest-hop restrictions
|
// closest-hop restrictions
|
||||||
@ -88,26 +95,101 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
|||||||
Set<Hash> moreExclude = getClosestHopExclude(false);
|
Set<Hash> moreExclude = getClosestHopExclude(false);
|
||||||
if (moreExclude != null) {
|
if (moreExclude != null) {
|
||||||
moreExclude.addAll(exclude);
|
moreExclude.addAll(exclude);
|
||||||
firstHopExclude = moreExclude;
|
lastHopExclude = moreExclude;
|
||||||
} else {
|
} else {
|
||||||
firstHopExclude = exclude;
|
lastHopExclude = exclude;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
firstHopExclude = exclude;
|
lastHopExclude = exclude;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
firstHopExclude = exclude;
|
lastHopExclude = exclude;
|
||||||
}
|
}
|
||||||
if (hiddenInbound) {
|
if (hiddenInbound) {
|
||||||
ctx.profileOrganizer().selectActiveNotFailingPeers(1, exclude, matches);
|
// IB closest hop
|
||||||
|
if (log.shouldInfo())
|
||||||
|
log.info("CPS SANFP closest IB exclude " + lastHopExclude.size());
|
||||||
|
// SANFP adds all not-connected to exclude, so make a copy
|
||||||
|
Set<Hash> SANFPExclude = new HashSet<Hash>(lastHopExclude);
|
||||||
|
ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, matches);
|
||||||
if (matches.isEmpty()) {
|
if (matches.isEmpty()) {
|
||||||
|
if (log.shouldInfo())
|
||||||
|
log.info("CPS SFP closest IB exclude " + lastHopExclude.size());
|
||||||
// ANFP does not fall back to non-connected
|
// ANFP does not fall back to non-connected
|
||||||
ctx.profileOrganizer().selectFastPeers(1, firstHopExclude, matches, settings.getRandomKey(), length == 2 ? SLICE_0_1 : SLICE_0);
|
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
|
||||||
|
}
|
||||||
|
} else if (hiddenOutbound) {
|
||||||
|
// OBEP
|
||||||
|
// check for hidden and outbound, and the paired (inbound) tunnel is zero-hop
|
||||||
|
// if so, we need the OBEP to be connected to us, so we get the build reply back
|
||||||
|
// This should be rare except at startup
|
||||||
|
TunnelManagerFacade tmf = ctx.tunnelManager();
|
||||||
|
TunnelPool tp = tmf.getInboundPool(settings.getDestination());
|
||||||
|
boolean pickFurthest;
|
||||||
|
if (tp != null) {
|
||||||
|
pickFurthest = true;
|
||||||
|
TunnelPoolSettings tps = tp.getSettings();
|
||||||
|
int len = tps.getLength();
|
||||||
|
if (len <= 0 ||
|
||||||
|
tps.getLengthOverride() == 0 ||
|
||||||
|
len + tps.getLengthVariance() <= 0) {
|
||||||
|
// leave it true
|
||||||
|
} else {
|
||||||
|
List<TunnelInfo> tunnels = tp.listTunnels();
|
||||||
|
if (!tunnels.isEmpty()) {
|
||||||
|
for (TunnelInfo ti : tp.listTunnels()) {
|
||||||
|
if (ti.getLength() > 1) {
|
||||||
|
pickFurthest = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// no tunnels in the paired tunnel pool
|
||||||
|
// BuildRequester will be using exploratory
|
||||||
|
tp = tmf.getInboundExploratoryPool();
|
||||||
|
tps = tp.getSettings();
|
||||||
|
len = tps.getLength();
|
||||||
|
if (len <= 0 ||
|
||||||
|
tps.getLengthOverride() == 0 ||
|
||||||
|
len + tps.getLengthVariance() <= 0) {
|
||||||
|
// leave it true
|
||||||
|
} else {
|
||||||
|
tunnels = tp.listTunnels();
|
||||||
|
if (!tunnels.isEmpty()) {
|
||||||
|
for (TunnelInfo ti : tp.listTunnels()) {
|
||||||
|
if (ti.getLength() > 1) {
|
||||||
|
pickFurthest = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// shouldn't happen
|
||||||
|
pickFurthest = false;
|
||||||
|
}
|
||||||
|
if (pickFurthest) {
|
||||||
|
if (log.shouldInfo())
|
||||||
|
log.info("CPS SANFP OBEP exclude " + lastHopExclude.size());
|
||||||
|
// SANFP adds all not-connected to exclude, so make a copy
|
||||||
|
Set<Hash> SANFPExclude = new HashSet<Hash>(lastHopExclude);
|
||||||
|
ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, matches);
|
||||||
|
if (matches.isEmpty()) {
|
||||||
|
// ANFP does not fall back to non-connected
|
||||||
|
if (log.shouldInfo())
|
||||||
|
log.info("CPS SFP OBEP exclude " + lastHopExclude.size());
|
||||||
|
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO exclude IPv6-only at OBEP? Caught in checkTunnel() below
|
// TODO exclude IPv6-only at OBEP? Caught in checkTunnel() below
|
||||||
ctx.profileOrganizer().selectFastPeers(1, firstHopExclude, matches, settings.getRandomKey(), length == 2 ? SLICE_0_1 : SLICE_0);
|
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
matches.remove(ctx.routerHash());
|
matches.remove(ctx.routerHash());
|
||||||
exclude.addAll(matches);
|
exclude.addAll(matches);
|
||||||
rv.addAll(matches);
|
rv.addAll(matches);
|
||||||
@ -115,12 +197,12 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
|||||||
if (length > 2) {
|
if (length > 2) {
|
||||||
// middle hop(s)
|
// middle hop(s)
|
||||||
// group 2 or 3
|
// group 2 or 3
|
||||||
ctx.profileOrganizer().selectFastPeers(length - 2, exclude, matches, settings.getRandomKey(), SLICE_2_3);
|
ctx.profileOrganizer().selectFastPeers(length - 2, exclude, matches, randomKey, SLICE_2_3);
|
||||||
matches.remove(ctx.routerHash());
|
matches.remove(ctx.routerHash());
|
||||||
if (matches.size() > 1) {
|
if (matches.size() > 1) {
|
||||||
// order the middle peers for tunnels >= 4 hops
|
// order the middle peers for tunnels >= 4 hops
|
||||||
List<Hash> ordered = new ArrayList<Hash>(matches);
|
List<Hash> ordered = new ArrayList<Hash>(matches);
|
||||||
orderPeers(ordered, settings.getRandomKey());
|
orderPeers(ordered, randomKey);
|
||||||
rv.addAll(ordered);
|
rv.addAll(ordered);
|
||||||
} else {
|
} else {
|
||||||
rv.addAll(matches);
|
rv.addAll(matches);
|
||||||
@ -128,6 +210,7 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
|||||||
exclude.addAll(matches);
|
exclude.addAll(matches);
|
||||||
matches.clear();
|
matches.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// IBGW or OB first hop
|
// IBGW or OB first hop
|
||||||
// group 2 or 3 if two hops, otherwise group 1
|
// group 2 or 3 if two hops, otherwise group 1
|
||||||
if (!isInbound) {
|
if (!isInbound) {
|
||||||
@ -140,7 +223,7 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO exclude IPv6-only at IBGW? Caught in checkTunnel() below
|
// TODO exclude IPv6-only at IBGW? Caught in checkTunnel() below
|
||||||
ctx.profileOrganizer().selectFastPeers(1, exclude, matches, settings.getRandomKey(), length == 2 ? SLICE_2_3 : SLICE_1);
|
ctx.profileOrganizer().selectFastPeers(1, exclude, matches, randomKey, length == 2 ? SLICE_2_3 : SLICE_1);
|
||||||
matches.remove(ctx.routerHash());
|
matches.remove(ctx.routerHash());
|
||||||
rv.addAll(matches);
|
rv.addAll(matches);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ import java.util.Set;
|
|||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
import net.i2p.data.Hash;
|
import net.i2p.data.Hash;
|
||||||
import net.i2p.router.RouterContext;
|
import net.i2p.router.RouterContext;
|
||||||
|
import net.i2p.router.TunnelInfo;
|
||||||
|
import net.i2p.router.TunnelManagerFacade;
|
||||||
import net.i2p.router.TunnelPoolSettings;
|
import net.i2p.router.TunnelPoolSettings;
|
||||||
import net.i2p.stat.Rate;
|
import net.i2p.stat.Rate;
|
||||||
import net.i2p.stat.RateStat;
|
import net.i2p.stat.RateStat;
|
||||||
@ -65,6 +67,7 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
|||||||
boolean hidden = nonzero && (ctx.router().isHidden() ||
|
boolean hidden = nonzero && (ctx.router().isHidden() ||
|
||||||
ctx.router().getRouterInfo().getAddressCount() <= 0);
|
ctx.router().getRouterInfo().getAddressCount() <= 0);
|
||||||
boolean hiddenInbound = hidden && isInbound;
|
boolean hiddenInbound = hidden && isInbound;
|
||||||
|
boolean hiddenOutbound = hidden && !isInbound;
|
||||||
boolean lowOutbound = nonzero && !isInbound && !ctx.commSystem().haveHighOutboundCapacity();
|
boolean lowOutbound = nonzero && !isInbound && !ctx.commSystem().haveHighOutboundCapacity();
|
||||||
|
|
||||||
|
|
||||||
@ -93,7 +96,9 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
|||||||
// use only connected peers so we don't make more connections
|
// use only connected peers so we don't make more connections
|
||||||
if (log.shouldLog(Log.INFO))
|
if (log.shouldLog(Log.INFO))
|
||||||
log.info("EPS SANFP closest " + (isInbound ? "IB" : "OB") + " exclude " + closestExclude.size());
|
log.info("EPS SANFP closest " + (isInbound ? "IB" : "OB") + " exclude " + closestExclude.size());
|
||||||
ctx.profileOrganizer().selectActiveNotFailingPeers(1, closestExclude, closest);
|
// SANFP adds all not-connected to exclude, so make a copy
|
||||||
|
Set<Hash> SANFPExclude = new HashSet<Hash>(closestExclude);
|
||||||
|
ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, closest);
|
||||||
if (closest.isEmpty()) {
|
if (closest.isEmpty()) {
|
||||||
// ANFP does not fall back to non-connected
|
// ANFP does not fall back to non-connected
|
||||||
if (log.shouldLog(Log.INFO))
|
if (log.shouldLog(Log.INFO))
|
||||||
@ -116,6 +121,55 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// furthest-hop restrictions
|
||||||
|
// Since we're applying orderPeers() later, we don't know
|
||||||
|
// which will be the furthest hop, so select the furthest one here if necessary.
|
||||||
|
|
||||||
|
Hash furthestHop = null;
|
||||||
|
if (hiddenOutbound && length > 0) {
|
||||||
|
// OBEP
|
||||||
|
// check for hidden and outbound, and the paired (inbound) tunnel is zero-hop
|
||||||
|
// if so, we need the OBEP to be connected to us, so we get the build reply back
|
||||||
|
// This should be rare except at startup
|
||||||
|
TunnelManagerFacade tmf = ctx.tunnelManager();
|
||||||
|
TunnelPool tp = tmf.getInboundExploratoryPool();
|
||||||
|
TunnelPoolSettings tps = tp.getSettings();
|
||||||
|
int len = tps.getLength();
|
||||||
|
boolean pickFurthest = true;
|
||||||
|
if (len <= 0 ||
|
||||||
|
tps.getLengthOverride() == 0 ||
|
||||||
|
len + tps.getLengthVariance() <= 0) {
|
||||||
|
// leave it true
|
||||||
|
} else {
|
||||||
|
for (TunnelInfo ti : tp.listTunnels()) {
|
||||||
|
if (ti.getLength() > 1) {
|
||||||
|
pickFurthest = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pickFurthest) {
|
||||||
|
Set<Hash> furthest = new HashSet<Hash>(1);
|
||||||
|
if (log.shouldLog(Log.INFO))
|
||||||
|
log.info("EPS SANFP furthest OB exclude " + exclude.size());
|
||||||
|
// ANFP adds all not-connected to exclude, so make a copy
|
||||||
|
Set<Hash> SANFPExclude = new HashSet<Hash>(exclude);
|
||||||
|
ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, furthest);
|
||||||
|
if (furthest.isEmpty()) {
|
||||||
|
// ANFP does not fall back to non-connected
|
||||||
|
if (log.shouldLog(Log.INFO))
|
||||||
|
log.info("EPS SFP furthest OB exclude " + exclude.size());
|
||||||
|
ctx.profileOrganizer().selectFastPeers(1, exclude, furthest);
|
||||||
|
}
|
||||||
|
if (!furthest.isEmpty()) {
|
||||||
|
furthestHop = furthest.iterator().next();
|
||||||
|
exclude.add(furthestHop);
|
||||||
|
length--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Don't use ff peers for exploratory tunnels to lessen exposure to netDb searches and stores
|
// 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
|
// Hmm if they don't get explored they don't get a speed/capacity rating
|
||||||
// so they don't get used for client tunnels either.
|
// so they don't get used for client tunnels either.
|
||||||
@ -154,6 +208,14 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
|||||||
rv.add(closestHop);
|
rv.add(closestHop);
|
||||||
length++;
|
length++;
|
||||||
}
|
}
|
||||||
|
if (furthestHop != null) {
|
||||||
|
// always OBEP for now, nothing special for IBGW
|
||||||
|
if (isInbound)
|
||||||
|
rv.add(furthestHop);
|
||||||
|
else
|
||||||
|
rv.add(0, furthestHop);
|
||||||
|
length++;
|
||||||
|
}
|
||||||
//if (length != rv.size() && log.shouldWarn())
|
//if (length != rv.size() && log.shouldWarn())
|
||||||
// log.warn("EPS requested " + length + " got " + rv.size() + ": " + DataHelper.toString(rv));
|
// log.warn("EPS requested " + length + " got " + rv.size() + ": " + DataHelper.toString(rv));
|
||||||
//else if (log.shouldDebug())
|
//else if (log.shouldDebug())
|
||||||
|
@ -729,6 +729,22 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
|||||||
return _outboundExploratory;
|
return _outboundExploratory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return pool or null
|
||||||
|
* @since 0.9.34
|
||||||
|
*/
|
||||||
|
public TunnelPool getInboundPool(Hash client) {
|
||||||
|
return _clientInboundPools.get(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return pool or null
|
||||||
|
* @since 0.9.34
|
||||||
|
*/
|
||||||
|
public TunnelPool getOutboundPool(Hash client) {
|
||||||
|
return _clientOutboundPools.get(client);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fail all outbound tunnels with this peer as first hop,
|
* Fail all outbound tunnels with this peer as first hop,
|
||||||
* and all inbound tunnels with this peer as the last hop,
|
* and all inbound tunnels with this peer as the last hop,
|
||||||
|
Reference in New Issue
Block a user