forked from I2P_Developers/i2p.i2p
Compare commits
2 Commits
i2p.i2p.2.
...
idk/i2p.i2
Author | SHA1 | Date | |
---|---|---|---|
d3af2af369 | |||
257c0aff42 |
@ -407,7 +407,7 @@ public class ProfileOrganizer {
|
||||
*
|
||||
*/
|
||||
public void selectFastPeers(int howMany, Set<Hash> exclude, Set<Hash> matches) {
|
||||
selectFastPeers(howMany, exclude, matches, 0);
|
||||
selectFastPeers(howMany, exclude, matches, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -421,17 +421,19 @@ public class ProfileOrganizer {
|
||||
* @param matches set to store the return value in
|
||||
* @param mask 0-4 Number of bytes to match to determine if peers in the same IP range should
|
||||
* not be in the same tunnel. 0 = disable check; 1 = /8; 2 = /16; 3 = /24; 4 = exact IP match
|
||||
* @param ipSet in/out param, use for multiple calls, may be null only if mask is 0
|
||||
* @since 0.9.53 added ipSet param
|
||||
*
|
||||
*/
|
||||
public void selectFastPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, int mask) {
|
||||
public void selectFastPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, int mask, MaskedIPSet ipSet) {
|
||||
getReadLock();
|
||||
try {
|
||||
locked_selectPeers(_fastPeers, howMany, exclude, matches, mask);
|
||||
locked_selectPeers(_fastPeers, howMany, exclude, matches, mask, ipSet);
|
||||
} finally { releaseReadLock(); }
|
||||
if (matches.size() < howMany) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("selectFastPeers("+howMany+"), not enough fast (" + matches.size() + ") going on to highCap");
|
||||
selectHighCapacityPeers(howMany, exclude, matches, mask);
|
||||
selectHighCapacityPeers(howMany, exclude, matches, mask, ipSet);
|
||||
} else {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("selectFastPeers("+howMany+"), found enough fast (" + matches.size() + ")");
|
||||
@ -482,8 +484,12 @@ public class ProfileOrganizer {
|
||||
* 6: return only from group 2
|
||||
* 7: return only from group 3
|
||||
*</pre>
|
||||
* @param mask 0-4
|
||||
* @param ipSet in/out param, use for multiple calls, may be null only if mask is 0
|
||||
* @since 0.9.53 added mask and ipSet params
|
||||
*/
|
||||
public void selectFastPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, SessionKey randomKey, Slice subTierMode) {
|
||||
public void selectFastPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, SessionKey randomKey,
|
||||
Slice subTierMode, int mask, MaskedIPSet ipSet) {
|
||||
getReadLock();
|
||||
try {
|
||||
if (subTierMode != Slice.SLICE_ALL) {
|
||||
@ -492,14 +498,14 @@ public class ProfileOrganizer {
|
||||
subTierMode = Slice.SLICE_ALL;
|
||||
}
|
||||
if (subTierMode != Slice.SLICE_ALL)
|
||||
locked_selectPeers(_fastPeers, howMany, exclude, matches, randomKey, subTierMode);
|
||||
locked_selectPeers(_fastPeers, howMany, exclude, matches, randomKey, subTierMode, mask, ipSet);
|
||||
else
|
||||
locked_selectPeers(_fastPeers, howMany, exclude, matches, 2);
|
||||
locked_selectPeers(_fastPeers, howMany, exclude, matches, mask, ipSet);
|
||||
} finally { releaseReadLock(); }
|
||||
if (matches.size() < howMany) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("selectFastPeers("+howMany+"), not enough fast (" + matches.size() + ") going on to highCap");
|
||||
selectHighCapacityPeers(howMany, exclude, matches, 2);
|
||||
selectHighCapacityPeers(howMany, exclude, matches, mask, ipSet);
|
||||
} else {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("selectFastPeers("+howMany+"), found enough fast (" + matches.size() + ")");
|
||||
@ -512,14 +518,16 @@ public class ProfileOrganizer {
|
||||
*
|
||||
*/
|
||||
public void selectHighCapacityPeers(int howMany, Set<Hash> exclude, Set<Hash> matches) {
|
||||
selectHighCapacityPeers(howMany, exclude, matches, 0);
|
||||
selectHighCapacityPeers(howMany, exclude, matches, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mask 0-4 Number of bytes to match to determine if peers in the same IP range should
|
||||
* not be in the same tunnel. 0 = disable check; 1 = /8; 2 = /16; 3 = /24; 4 = exact IP match
|
||||
* @param ipSet in/out param, use for multiple calls, may be null only if mask is 0
|
||||
* @since 0.9.53 added ipSet param
|
||||
*/
|
||||
public void selectHighCapacityPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, int mask) {
|
||||
public void selectHighCapacityPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, int mask, MaskedIPSet ipSet) {
|
||||
getReadLock();
|
||||
try {
|
||||
// we only use selectHighCapacityPeers when we are selecting for PURPOSE_TEST
|
||||
@ -531,12 +539,12 @@ public class ProfileOrganizer {
|
||||
else
|
||||
exclude.addAll(_fastPeers.keySet());
|
||||
*/
|
||||
locked_selectPeers(_highCapacityPeers, howMany, exclude, matches, mask);
|
||||
locked_selectPeers(_highCapacityPeers, howMany, exclude, matches, mask, ipSet);
|
||||
} finally { releaseReadLock(); }
|
||||
if (matches.size() < howMany) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("selectHighCap("+howMany+"), not enough highcap (" + matches.size() + ") going on to ANFP2");
|
||||
selectActiveNotFailingPeers2(howMany, exclude, matches, mask);
|
||||
selectActiveNotFailingPeers2(howMany, exclude, matches, mask, ipSet);
|
||||
} else {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("selectHighCap("+howMany+"), found enough highCap (" + matches.size() + ")");
|
||||
@ -551,7 +559,7 @@ public class ProfileOrganizer {
|
||||
*/
|
||||
@Deprecated
|
||||
public void selectWellIntegratedPeers(int howMany, Set<Hash> exclude, Set<Hash> matches) {
|
||||
selectWellIntegratedPeers(howMany, exclude, matches, 0);
|
||||
selectWellIntegratedPeers(howMany, exclude, matches, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -559,18 +567,19 @@ public class ProfileOrganizer {
|
||||
*
|
||||
* @param mask 0-4 Number of bytes to match to determine if peers in the same IP range should
|
||||
* not be in the same tunnel. 0 = disable check; 1 = /8; 2 = /16; 3 = /24; 4 = exact IP match
|
||||
* @since 0.9.53 added ipSet param
|
||||
* @deprecated unused
|
||||
*/
|
||||
@Deprecated
|
||||
public void selectWellIntegratedPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, int mask) {
|
||||
public void selectWellIntegratedPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, int mask, MaskedIPSet ipSet) {
|
||||
getReadLock();
|
||||
try {
|
||||
locked_selectPeers(_wellIntegratedPeers, howMany, exclude, matches, mask);
|
||||
locked_selectPeers(_wellIntegratedPeers, howMany, exclude, matches, mask, ipSet);
|
||||
} finally { releaseReadLock(); }
|
||||
if (matches.size() < howMany) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("selectWellIntegrated("+howMany+"), not enough integrated (" + matches.size() + ") going on to notFailing");
|
||||
selectNotFailingPeers(howMany, exclude, matches, mask);
|
||||
selectNotFailingPeers(howMany, exclude, matches, mask, ipSet);
|
||||
} else {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("selectWellIntegrated("+howMany+"), found enough well integrated (" + matches.size() + ")");
|
||||
@ -585,18 +594,20 @@ public class ProfileOrganizer {
|
||||
*
|
||||
*/
|
||||
public void selectNotFailingPeers(int howMany, Set<Hash> exclude, Set<Hash> matches) {
|
||||
selectNotFailingPeers(howMany, exclude, matches, false, 0);
|
||||
selectNotFailingPeers(howMany, exclude, matches, false, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mask ignored, should call locked_selectPeers, to be fixed
|
||||
* @param ipSet ignored, should call locked_selectPeers, to be fixed
|
||||
* @since 0.9.53 added ipSet param
|
||||
*/
|
||||
public void selectNotFailingPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, int mask) {
|
||||
selectNotFailingPeers(howMany, exclude, matches, false, mask);
|
||||
public void selectNotFailingPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, int mask, MaskedIPSet ipSet) {
|
||||
selectNotFailingPeers(howMany, exclude, matches, false, mask, ipSet);
|
||||
}
|
||||
|
||||
public void selectNotFailingPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, boolean onlyNotFailing) {
|
||||
selectNotFailingPeers(howMany, exclude, matches, onlyNotFailing, 0);
|
||||
selectNotFailingPeers(howMany, exclude, matches, onlyNotFailing, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -608,8 +619,11 @@ public class ProfileOrganizer {
|
||||
* @param matches set to store the matches in
|
||||
* @param onlyNotFailing if true, don't include any high capacity peers
|
||||
* @param mask ignored, should call locked_selectPeers, to be fixed
|
||||
* @param ipSet ignored, should call locked_selectPeers, to be fixed
|
||||
* @since 0.9.53 added ipSet param
|
||||
*/
|
||||
public void selectNotFailingPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, boolean onlyNotFailing, int mask) {
|
||||
public void selectNotFailingPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, boolean onlyNotFailing,
|
||||
int mask, MaskedIPSet ipSet) {
|
||||
if (matches.size() < howMany)
|
||||
selectAllNotFailingPeers(howMany, exclude, matches, onlyNotFailing, mask);
|
||||
return;
|
||||
@ -627,9 +641,30 @@ public class ProfileOrganizer {
|
||||
* be used when there is a good number of connected peers.
|
||||
*
|
||||
* @param exclude non-null, WARNING - side effect, all not-connected peers are added
|
||||
* No mask parameter, to be fixed
|
||||
*/
|
||||
public void selectActiveNotFailingPeers(int howMany, Set<Hash> exclude, Set<Hash> matches) {
|
||||
selectActiveNotFailingPeers(howMany, exclude, matches, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a set of Hashes for peers that are both not failing and we're actively
|
||||
* talking with.
|
||||
*
|
||||
* We use commSystem().isEstablished(), not profile.getIsActive(), as the
|
||||
* NTCP idle time is now shorter than the 5 minute getIsActive() threshold,
|
||||
* and we're using this to try and limit connections.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @param exclude non-null, WARNING - side effect, all not-connected peers are added
|
||||
* @param mask 0-4 Number of bytes to match to determine if peers in the same IP range should
|
||||
* not be in the same tunnel. 0 = disable check; 1 = /8; 2 = /16; 3 = /24; 4 = exact IP match
|
||||
* @param ipSet ignored, should call locked_selectPeers, to be fixed
|
||||
* @param ipSet may be null only if mask is 0
|
||||
* @since 0.9.53
|
||||
*/
|
||||
public void selectActiveNotFailingPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, int mask, MaskedIPSet ipSet) {
|
||||
if (matches.size() < howMany) {
|
||||
Set<Hash> connected = _context.commSystem().getEstablished();
|
||||
getReadLock();
|
||||
@ -638,7 +673,7 @@ public class ProfileOrganizer {
|
||||
if (!connected.contains(peer))
|
||||
exclude.add(peer);
|
||||
}
|
||||
locked_selectPeers(_notFailingPeers, howMany, exclude, matches, 0);
|
||||
locked_selectPeers(_notFailingPeers, howMany, exclude, matches, mask, ipSet);
|
||||
} finally { releaseReadLock(); }
|
||||
}
|
||||
}
|
||||
@ -655,8 +690,10 @@ public class ProfileOrganizer {
|
||||
*
|
||||
* @param mask 0-4 Number of bytes to match to determine if peers in the same IP range should
|
||||
* not be in the same tunnel. 0 = disable check; 1 = /8; 2 = /16; 3 = /24; 4 = exact IP match
|
||||
* @param ipSet in/out param, use for multiple calls, may be null only if mask is 0
|
||||
* @since 0.9.53 added ipSet param
|
||||
*/
|
||||
private void selectActiveNotFailingPeers2(int howMany, Set<Hash> exclude, Set<Hash> matches, int mask) {
|
||||
private void selectActiveNotFailingPeers2(int howMany, Set<Hash> exclude, Set<Hash> matches, int mask, MaskedIPSet ipSet) {
|
||||
if (matches.size() < howMany) {
|
||||
Set<Hash> connected = _context.commSystem().getEstablished();
|
||||
Map<Hash, PeerProfile> activePeers = new HashMap<Hash, PeerProfile>(connected.size());
|
||||
@ -667,13 +704,13 @@ public class ProfileOrganizer {
|
||||
if (prof != null)
|
||||
activePeers.put(peer, prof);
|
||||
}
|
||||
locked_selectPeers(activePeers, howMany, exclude, matches, mask);
|
||||
locked_selectPeers(activePeers, howMany, exclude, matches, mask, ipSet);
|
||||
} finally { releaseReadLock(); }
|
||||
}
|
||||
if (matches.size() < howMany) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("selectANFP2("+howMany+"), not enough ANFP (" + matches.size() + ") going on to notFailing");
|
||||
selectNotFailingPeers(howMany, exclude, matches, mask);
|
||||
selectNotFailingPeers(howMany, exclude, matches, mask, ipSet);
|
||||
} else {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("selectANFP2("+howMany+"), found enough ANFP (" + matches.size() + ")");
|
||||
@ -690,7 +727,6 @@ public class ProfileOrganizer {
|
||||
|
||||
/**
|
||||
* @param mask ignored, should call locked_selectPeers, to be fixed
|
||||
*
|
||||
*/
|
||||
private void selectAllNotFailingPeers(int howMany, Set<Hash> exclude, Set<Hash> matches, boolean onlyNotFailing, int mask) {
|
||||
if (matches.size() < howMany) {
|
||||
@ -1287,19 +1323,21 @@ public class ProfileOrganizer {
|
||||
*
|
||||
*/
|
||||
private void locked_selectPeers(Map<Hash, PeerProfile> peers, int howMany, Set<Hash> toExclude, Set<Hash> matches) {
|
||||
locked_selectPeers(peers, howMany, toExclude, matches, 0);
|
||||
locked_selectPeers(peers, howMany, toExclude, matches, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* As of 0.9.24, checks for a netdb family match as well, unless mask == 0.
|
||||
*
|
||||
*
|
||||
* As of 0.9.24, checks for a netdb family match as well, unless mask == 0.
|
||||
*
|
||||
* @param mask 0-4 Number of bytes to match to determine if peers in the same IP range should
|
||||
* not be in the same tunnel. 0 = disable check; 1 = /8; 2 = /16; 3 = /24; 4 = exact IP match
|
||||
* @param ipSet may be null only if mask is 0
|
||||
* @since 0.9.53 added ipSet param
|
||||
*/
|
||||
private void locked_selectPeers(Map<Hash, PeerProfile> peers, int howMany, Set<Hash> toExclude, Set<Hash> matches, int mask) {
|
||||
private void locked_selectPeers(Map<Hash, PeerProfile> peers, int howMany, Set<Hash> toExclude, Set<Hash> matches,
|
||||
int mask, MaskedIPSet ipSet) {
|
||||
List<Hash> all = new ArrayList<Hash>(peers.keySet());
|
||||
MaskedIPSet IPSet = new MaskedIPSet(16);
|
||||
// use RandomIterator to avoid shuffling the whole thing
|
||||
for (Iterator<Hash> iter = new RandomIterator<Hash>(all); (matches.size() < howMany) && iter.hasNext(); ) {
|
||||
Hash peer = iter.next();
|
||||
@ -1311,7 +1349,7 @@ public class ProfileOrganizer {
|
||||
continue;
|
||||
boolean ok = isSelectable(peer);
|
||||
if (ok) {
|
||||
ok = mask <= 0 || notRestricted(peer, IPSet, mask);
|
||||
ok = mask <= 0 || notRestricted(peer, ipSet, mask);
|
||||
if ((!ok) && _log.shouldLog(Log.WARN))
|
||||
_log.warn("IP restriction prevents " + peer + " from joining " + matches);
|
||||
}
|
||||
@ -1350,9 +1388,13 @@ public class ProfileOrganizer {
|
||||
* 6: return only from group 2
|
||||
* 7: return only from group 3
|
||||
*</pre>
|
||||
* @param mask is 1-4 (number of bytes to match)
|
||||
* @param IPMatches all IPs so far, modified by this routine
|
||||
* @since 0.9.53 added mask/ipSet params
|
||||
*/
|
||||
private void locked_selectPeers(Map<Hash, PeerProfile> peers, int howMany, Set<Hash> toExclude,
|
||||
Set<Hash> matches, SessionKey randomKey, Slice subTierMode) {
|
||||
Set<Hash> matches, SessionKey randomKey, Slice subTierMode,
|
||||
int mask, MaskedIPSet ipSet) {
|
||||
List<Hash> all = new ArrayList<Hash>(peers.keySet());
|
||||
byte[] rk = randomKey.getData();
|
||||
// we use the first half of the random key here,
|
||||
@ -1373,6 +1415,11 @@ public class ProfileOrganizer {
|
||||
if ((subTier & subTierMode.mask) != subTierMode.val)
|
||||
continue;
|
||||
boolean ok = isSelectable(peer);
|
||||
if (ok) {
|
||||
ok = mask <= 0 || notRestricted(peer, ipSet, mask);
|
||||
if ((!ok) && _log.shouldLog(Log.WARN))
|
||||
_log.warn("IP restriction prevents " + peer + " from joining " + matches);
|
||||
}
|
||||
if (ok)
|
||||
matches.add(peer);
|
||||
else
|
||||
|
@ -13,6 +13,7 @@ import net.i2p.router.TunnelInfo;
|
||||
import net.i2p.router.TunnelManagerFacade;
|
||||
import net.i2p.router.TunnelPoolSettings;
|
||||
import static net.i2p.router.peermanager.ProfileOrganizer.Slice.*;
|
||||
import net.i2p.router.util.MaskedIPSet;
|
||||
|
||||
/**
|
||||
* Pick peers randomly out of the fast pool, and put them into tunnels
|
||||
@ -29,7 +30,7 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
||||
* Returns ENDPOINT FIRST, GATEWAY LAST!!!!
|
||||
* In: us .. closest .. middle .. IBGW
|
||||
* Out: OBGW .. middle .. closest .. us
|
||||
*
|
||||
*
|
||||
* @return ordered list of Hash objects (one per peer) specifying what order
|
||||
* they should appear in a tunnel (ENDPOINT FIRST). This includes
|
||||
* the local router in the list. If there are no tunnels or peers
|
||||
@ -45,7 +46,7 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
||||
|
||||
List<Hash> rv;
|
||||
boolean isInbound = settings.isInbound();
|
||||
|
||||
|
||||
if (length > 0) {
|
||||
// special cases
|
||||
boolean v6Only = isIPv6Only();
|
||||
@ -57,10 +58,12 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
||||
!ctx.commSystem().haveInboundCapacity(95);
|
||||
boolean hiddenInbound = hidden && isInbound;
|
||||
boolean hiddenOutbound = hidden && !isInbound;
|
||||
int ipRestriction = (ctx.getBooleanProperty("i2np.allowLocal") || length <= 1) ? 0 : settings.getIPRestriction();
|
||||
MaskedIPSet ipSet = ipRestriction > 0 ? new MaskedIPSet(16) : null;
|
||||
|
||||
if (shouldSelectExplicit(settings))
|
||||
return selectExplicit(settings, length);
|
||||
|
||||
|
||||
Set<Hash> exclude = getExclude(isInbound, false);
|
||||
Set<Hash> matches = new HashSet<Hash>(length);
|
||||
if (length == 1) {
|
||||
@ -70,6 +73,7 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
||||
if (moreExclude != null)
|
||||
exclude.addAll(moreExclude);
|
||||
}
|
||||
// 1-hop, IP restrictions not required here
|
||||
if (hiddenInbound) {
|
||||
// SANFP adds all not-connected to exclude, so make a copy
|
||||
Set<Hash> SANFPExclude = new HashSet<Hash>(exclude);
|
||||
@ -77,7 +81,7 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
||||
}
|
||||
if (matches.isEmpty()) {
|
||||
// ANFP does not fall back to non-connected
|
||||
ctx.profileOrganizer().selectFastPeers(length, exclude, matches, 0);
|
||||
ctx.profileOrganizer().selectFastPeers(length, exclude, matches);
|
||||
}
|
||||
matches.remove(ctx.routerHash());
|
||||
rv = new ArrayList<Hash>(matches);
|
||||
@ -108,17 +112,17 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
||||
lastHopExclude = exclude;
|
||||
}
|
||||
if (hiddenInbound) {
|
||||
// IB closest hop
|
||||
// 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);
|
||||
ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, matches, ipRestriction, ipSet);
|
||||
if (matches.isEmpty()) {
|
||||
if (log.shouldInfo())
|
||||
log.info("CPS SFP closest IB exclude " + lastHopExclude.size());
|
||||
// ANFP does not fall back to non-connected
|
||||
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
|
||||
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0, ipRestriction, ipSet);
|
||||
}
|
||||
} else if (hiddenOutbound) {
|
||||
// OBEP
|
||||
@ -177,19 +181,19 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
||||
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);
|
||||
ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, matches, ipRestriction, ipSet);
|
||||
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);
|
||||
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0, ipRestriction, ipSet);
|
||||
}
|
||||
} else {
|
||||
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
|
||||
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0, ipRestriction, ipSet);
|
||||
}
|
||||
} else {
|
||||
// TODO exclude IPv6-only at OBEP? Caught in checkTunnel() below
|
||||
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0);
|
||||
ctx.profileOrganizer().selectFastPeers(1, lastHopExclude, matches, randomKey, length == 2 ? SLICE_0_1 : SLICE_0, ipRestriction, ipSet);
|
||||
}
|
||||
|
||||
matches.remove(ctx.routerHash());
|
||||
@ -199,7 +203,7 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
||||
if (length > 2) {
|
||||
// middle hop(s)
|
||||
// group 2 or 3
|
||||
ctx.profileOrganizer().selectFastPeers(length - 2, exclude, matches, randomKey, SLICE_2_3);
|
||||
ctx.profileOrganizer().selectFastPeers(length - 2, exclude, matches, randomKey, SLICE_2_3, ipRestriction, ipSet);
|
||||
matches.remove(ctx.routerHash());
|
||||
if (matches.size() > 1) {
|
||||
// order the middle peers for tunnels >= 4 hops
|
||||
@ -225,14 +229,14 @@ class ClientPeerSelector extends TunnelPeerSelector {
|
||||
}
|
||||
}
|
||||
// TODO exclude IPv6-only at IBGW? Caught in checkTunnel() below
|
||||
ctx.profileOrganizer().selectFastPeers(1, exclude, matches, randomKey, length == 2 ? SLICE_2_3 : SLICE_1);
|
||||
ctx.profileOrganizer().selectFastPeers(1, exclude, matches, randomKey, length == 2 ? SLICE_2_3 : SLICE_1, ipRestriction, ipSet);
|
||||
matches.remove(ctx.routerHash());
|
||||
rv.addAll(matches);
|
||||
}
|
||||
} else {
|
||||
rv = new ArrayList<Hash>(1);
|
||||
}
|
||||
|
||||
|
||||
//if (length != rv.size() && log.shouldWarn())
|
||||
// log.warn("CPS requested " + length + " got " + rv.size() + ": " + DataHelper.toString(rv));
|
||||
//else if (log.shouldDebug())
|
||||
|
@ -11,6 +11,7 @@ import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.TunnelInfo;
|
||||
import net.i2p.router.TunnelManagerFacade;
|
||||
import net.i2p.router.TunnelPoolSettings;
|
||||
import net.i2p.router.util.MaskedIPSet;
|
||||
import net.i2p.stat.Rate;
|
||||
import net.i2p.stat.RateStat;
|
||||
import net.i2p.util.Log;
|
||||
@ -31,7 +32,7 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
* Returns ENDPOINT FIRST, GATEWAY LAST!!!!
|
||||
* In: us .. closest .. middle .. IBGW
|
||||
* Out: OBGW .. middle .. closest .. us
|
||||
*
|
||||
*
|
||||
* @return ordered list of Hash objects (one per peer) specifying what order
|
||||
* they should appear in a tunnel (ENDPOINT FIRST). This includes
|
||||
* the local router in the list. If there are no tunnels or peers
|
||||
@ -40,19 +41,19 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
*/
|
||||
public List<Hash> selectPeers(TunnelPoolSettings settings) {
|
||||
int length = getLength(settings);
|
||||
if (length < 0) {
|
||||
if (length < 0) {
|
||||
if (log.shouldLog(Log.DEBUG))
|
||||
log.debug("Length requested is zero: " + settings);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
//if (false && shouldSelectExplicit(settings)) {
|
||||
// List<Hash> rv = selectExplicit(settings, length);
|
||||
// if (l.shouldLog(Log.DEBUG))
|
||||
// l.debug("Explicit peers selected: " + rv);
|
||||
// return rv;
|
||||
//}
|
||||
|
||||
|
||||
boolean isInbound = settings.isInbound();
|
||||
Set<Hash> exclude = getExclude(isInbound, true);
|
||||
exclude.add(ctx.routerHash());
|
||||
@ -70,6 +71,8 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
boolean hiddenInbound = hidden && isInbound;
|
||||
boolean hiddenOutbound = hidden && !isInbound;
|
||||
boolean lowOutbound = nonzero && !isInbound && !ctx.commSystem().haveHighOutboundCapacity();
|
||||
int ipRestriction = (ctx.getBooleanProperty("i2np.allowLocal") || length <= 1) ? 0 : settings.getIPRestriction();
|
||||
MaskedIPSet ipSet = ipRestriction > 0 ? new MaskedIPSet(16) : null;
|
||||
|
||||
|
||||
// closest-hop restrictions
|
||||
@ -99,21 +102,21 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
log.info("EPS SANFP closest " + (isInbound ? "IB" : "OB") + " exclude " + closestExclude.size());
|
||||
// SANFP adds all not-connected to exclude, so make a copy
|
||||
Set<Hash> SANFPExclude = new HashSet<Hash>(closestExclude);
|
||||
ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, closest);
|
||||
ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, closest, ipRestriction, ipSet);
|
||||
if (closest.isEmpty()) {
|
||||
// ANFP does not fall back to non-connected
|
||||
if (log.shouldLog(Log.INFO))
|
||||
log.info("EPS SFP closest " + (isInbound ? "IB" : "OB") + " exclude " + closestExclude.size());
|
||||
ctx.profileOrganizer().selectFastPeers(1, closestExclude, closest);
|
||||
ctx.profileOrganizer().selectFastPeers(1, closestExclude, closest, ipRestriction, ipSet);
|
||||
}
|
||||
} else if (exploreHighCap) {
|
||||
if (log.shouldLog(Log.INFO))
|
||||
log.info("EPS SHCP closest " + (isInbound ? "IB" : "OB") + " exclude " + closestExclude.size());
|
||||
ctx.profileOrganizer().selectHighCapacityPeers(1, closestExclude, closest);
|
||||
ctx.profileOrganizer().selectHighCapacityPeers(1, closestExclude, closest, ipRestriction, ipSet);
|
||||
} else {
|
||||
if (log.shouldLog(Log.INFO))
|
||||
log.info("EPS SNFP closest " + (isInbound ? "IB" : "OB") + " exclude " + closestExclude.size());
|
||||
ctx.profileOrganizer().selectNotFailingPeers(1, closestExclude, closest, false);
|
||||
ctx.profileOrganizer().selectNotFailingPeers(1, closestExclude, closest, false, ipRestriction, ipSet);
|
||||
}
|
||||
if (!closest.isEmpty()) {
|
||||
closestHop = closest.iterator().next();
|
||||
@ -155,12 +158,12 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
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);
|
||||
ctx.profileOrganizer().selectActiveNotFailingPeers(1, SANFPExclude, furthest, ipRestriction, ipSet);
|
||||
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);
|
||||
ctx.profileOrganizer().selectFastPeers(1, exclude, furthest, ipRestriction, ipSet);
|
||||
}
|
||||
if (!furthest.isEmpty()) {
|
||||
furthestHop = furthest.iterator().next();
|
||||
@ -179,13 +182,10 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
HashSet<Hash> matches = new HashSet<Hash>(length);
|
||||
|
||||
if (length > 0) {
|
||||
//
|
||||
// We don't honor IP Restriction here, to be fixed
|
||||
//
|
||||
if (exploreHighCap) {
|
||||
if (log.shouldLog(Log.INFO))
|
||||
log.info("EPS SHCP " + length + (isInbound ? " IB" : " OB") + " exclude " + exclude.size());
|
||||
ctx.profileOrganizer().selectHighCapacityPeers(length, exclude, matches);
|
||||
ctx.profileOrganizer().selectHighCapacityPeers(length, exclude, matches, ipRestriction, ipSet);
|
||||
} else {
|
||||
// As of 0.9.23, we include a max of 2 not failing peers,
|
||||
// to improve build success on 3-hop tunnels.
|
||||
@ -194,7 +194,7 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
ctx.profileOrganizer().selectHighCapacityPeers(length - 2, exclude, matches);
|
||||
if (log.shouldLog(Log.INFO))
|
||||
log.info("EPS SNFP " + length + (isInbound ? " IB" : " OB") + " exclude " + exclude.size());
|
||||
ctx.profileOrganizer().selectNotFailingPeers(length, exclude, matches, false);
|
||||
ctx.profileOrganizer().selectNotFailingPeers(length, exclude, matches, false, ipRestriction, ipSet);
|
||||
}
|
||||
matches.remove(ctx.routerHash());
|
||||
}
|
||||
@ -231,7 +231,7 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
private static final int MIN_NONFAILING_PCT = 15;
|
||||
private static final int MIN_ACTIVE_PEERS_STARTUP = 6;
|
||||
private static final int MIN_ACTIVE_PEERS = 12;
|
||||
@ -290,7 +290,7 @@ 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,
|
||||
@ -326,11 +326,11 @@ class ExploratoryPeerSelector extends TunnelPeerSelector {
|
||||
double pct = (double)(reject + timeout) / (accept + reject + timeout);
|
||||
return (int)(100 * pct);
|
||||
}
|
||||
|
||||
|
||||
/** Use current + last to get more recent and smoother data */
|
||||
private int getEvents(String stat, long period) {
|
||||
RateStat rs = ctx.statManager().getRate(stat);
|
||||
if (rs == null)
|
||||
if (rs == null)
|
||||
return 0;
|
||||
Rate r = rs.getRate(period);
|
||||
if (r == null)
|
||||
|
@ -32,7 +32,7 @@ import net.i2p.util.SystemVersion;
|
||||
import net.i2p.util.VersionComparator;
|
||||
|
||||
/**
|
||||
* Coordinate the selection of peers to go into a tunnel for one particular
|
||||
* Coordinate the selection of peers to go into a tunnel for one particular
|
||||
* pool.
|
||||
*
|
||||
*/
|
||||
@ -45,8 +45,8 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
}
|
||||
|
||||
/**
|
||||
* Which peers should go into the next tunnel for the given settings?
|
||||
*
|
||||
* Which peers should go into the next tunnel for the given settings?
|
||||
*
|
||||
* @return ordered list of Hash objects (one per peer) specifying what order
|
||||
* they should appear in a tunnel (ENDPOINT FIRST). This includes
|
||||
* the local router in the list. If there are no tunnels or peers
|
||||
@ -54,7 +54,7 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
* return null.
|
||||
*/
|
||||
public abstract List<Hash> selectPeers(TunnelPoolSettings settings);
|
||||
|
||||
|
||||
/**
|
||||
* @return randomized number of hops 0-7, not including ourselves
|
||||
*/
|
||||
@ -81,7 +81,7 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
else if (length > 7) // as documented in tunnel.html
|
||||
length = 7;
|
||||
/*
|
||||
if ( (ctx.tunnelManager().getOutboundTunnelCount() <= 0) ||
|
||||
if ( (ctx.tunnelManager().getOutboundTunnelCount() <= 0) ||
|
||||
(ctx.tunnelManager().getFreeTunnelCount() <= 0) ) {
|
||||
Log log = ctx.logManager().getLog(TunnelPeerSelector.class);
|
||||
// no tunnels to build tunnels with
|
||||
@ -98,7 +98,7 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
*/
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For debugging, also possibly for restricted routes?
|
||||
* Needs analysis and testing
|
||||
@ -118,7 +118,7 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For debugging, also possibly for restricted routes?
|
||||
* Needs analysis and testing
|
||||
@ -128,10 +128,10 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
String peers = null;
|
||||
Properties opts = settings.getUnknownOptions();
|
||||
peers = opts.getProperty("explicitPeers");
|
||||
|
||||
|
||||
if (peers == null)
|
||||
peers = ctx.getProperty("explicitPeers");
|
||||
|
||||
|
||||
List<Hash> rv = new ArrayList<Hash>();
|
||||
StringTokenizer tok = new StringTokenizer(peers, ",");
|
||||
while (tok.hasMoreTokens()) {
|
||||
@ -139,7 +139,7 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
Hash peer = new Hash();
|
||||
try {
|
||||
peer.fromBase64(peerStr);
|
||||
|
||||
|
||||
if (ctx.profileOrganizer().isSelectable(peer)) {
|
||||
rv.add(peer);
|
||||
} else {
|
||||
@ -150,14 +150,14 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
log.error("Explicit peer is improperly formatted (" + peerStr + ")", dfe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int sz = rv.size();
|
||||
if (sz == 0) {
|
||||
log.logAlways(Log.WARN, "No valid explicit peers found, building zero hop");
|
||||
} else if (sz > 1) {
|
||||
Collections.shuffle(rv, ctx.random());
|
||||
}
|
||||
|
||||
|
||||
while (rv.size() > length) {
|
||||
rv.remove(0);
|
||||
}
|
||||
@ -166,11 +166,12 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
Set<Hash> exclude = getExclude(settings.isInbound(), settings.isExploratory());
|
||||
exclude.addAll(rv);
|
||||
Set<Hash> matches = new HashSet<Hash>(more);
|
||||
ctx.profileOrganizer().selectFastPeers(more, exclude, matches, 0);
|
||||
// don't bother with IP restrictions here
|
||||
ctx.profileOrganizer().selectFastPeers(more, exclude, matches);
|
||||
rv.addAll(matches);
|
||||
Collections.shuffle(rv, ctx.random());
|
||||
}
|
||||
|
||||
|
||||
if (log.shouldLog(Log.INFO)) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
if (settings.getDestinationNickname() != null)
|
||||
@ -187,16 +188,16 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
buf.append(", out of ").append(sz).append(" (not including self)");
|
||||
log.info(buf.toString());
|
||||
}
|
||||
|
||||
|
||||
if (settings.isInbound())
|
||||
rv.add(0, ctx.routerHash());
|
||||
else
|
||||
rv.add(ctx.routerHash());
|
||||
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Pick peers that we want to avoid
|
||||
*/
|
||||
public Set<Hash> getExclude(boolean isInbound, boolean isExploratory) {
|
||||
@ -267,7 +268,7 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
peers.add(peer.getIdentity().calculateHash());
|
||||
// otherwise, it contains flags we aren't trying to focus on,
|
||||
// so don't exclude it based on published capacity
|
||||
|
||||
|
||||
if (filterUptime(ctx, isInbound, isExploratory)) {
|
||||
Properties opts = peer.getOptions();
|
||||
if (opts != null) {
|
||||
@ -298,7 +299,7 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
peers.add(peer.getIdentity().calculateHash());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
long infoAge = ctx.clock().now() - peer.getPublished();
|
||||
if (infoAge < 0) {
|
||||
infoAge = 0;
|
||||
@ -387,8 +388,8 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
return false;
|
||||
return canConnect(ANY_V4, ri);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Pick peers that we want to avoid for the first OB hop or last IB hop.
|
||||
* There's several cases of importance:
|
||||
* <ol><li>Inbound and we are hidden -
|
||||
@ -452,19 +453,19 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/** warning, this is also called by ProfileOrganizer.isSelectable() */
|
||||
public static boolean shouldExclude(RouterContext ctx, RouterInfo peer) {
|
||||
return shouldExclude(peer, getExcludeCaps(ctx));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return non-null, possibly empty
|
||||
*/
|
||||
private static String getExcludeCaps(RouterContext ctx) {
|
||||
return ctx.getProperty("router.excludePeerCaps", DEFAULT_EXCLUDE_CAPS);
|
||||
}
|
||||
|
||||
|
||||
/** NTCP2 */
|
||||
private static final String MIN_VERSION = "0.9.36";
|
||||
|
||||
@ -555,18 +556,18 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
******/
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private static final String PROP_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = "router.outboundExploratoryExcludeUnreachable";
|
||||
private static final String PROP_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE = "router.outboundClientExcludeUnreachable";
|
||||
private static final String PROP_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = "router.inboundExploratoryExcludeUnreachable";
|
||||
private static final String PROP_INBOUND_CLIENT_EXCLUDE_UNREACHABLE = "router.inboundClientExcludeUnreachable";
|
||||
|
||||
|
||||
private static final boolean DEFAULT_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = false;
|
||||
private static final boolean DEFAULT_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE = false;
|
||||
// see comments at getExclude() above
|
||||
private static final boolean DEFAULT_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = false;
|
||||
private static final boolean DEFAULT_INBOUND_CLIENT_EXCLUDE_UNREACHABLE = false;
|
||||
|
||||
|
||||
/**
|
||||
* do we want to skip unreachable peers?
|
||||
* @return true if yes
|
||||
@ -587,18 +588,18 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
if (ctx.router().isHidden())
|
||||
return true;
|
||||
return ctx.getProperty(PROP_INBOUND_CLIENT_EXCLUDE_UNREACHABLE, DEFAULT_INBOUND_CLIENT_EXCLUDE_UNREACHABLE);
|
||||
} else {
|
||||
} else {
|
||||
return ctx.getProperty(PROP_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE, DEFAULT_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static final String PROP_OUTBOUND_EXPLORATORY_EXCLUDE_SLOW = "router.outboundExploratoryExcludeSlow";
|
||||
private static final String PROP_OUTBOUND_CLIENT_EXCLUDE_SLOW = "router.outboundClientExcludeSlow";
|
||||
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
|
||||
@ -612,18 +613,18 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
} else {
|
||||
if (isInbound)
|
||||
return ctx.getProperty(PROP_INBOUND_CLIENT_EXCLUDE_SLOW, true);
|
||||
else
|
||||
else
|
||||
return ctx.getProperty(PROP_OUTBOUND_CLIENT_EXCLUDE_SLOW, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****
|
||||
private static final String PROP_OUTBOUND_EXPLORATORY_EXCLUDE_UPTIME = "router.outboundExploratoryExcludeUptime";
|
||||
private static final String PROP_OUTBOUND_CLIENT_EXCLUDE_UPTIME = "router.outboundClientExcludeUptime";
|
||||
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?
|
||||
* @return true unless configured otherwise
|
||||
@ -638,7 +639,7 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
} else {
|
||||
if (isInbound)
|
||||
return ctx.getProperty(PROP_INBOUND_CLIENT_EXCLUDE_UPTIME, true);
|
||||
else
|
||||
else
|
||||
return ctx.getProperty(PROP_OUTBOUND_CLIENT_EXCLUDE_UPTIME, true);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user