* Streaming:

- Check blacklist/whitelist before connection limits, so
     a blacklisted peer does not increment the counters
   - Don't increment total throttle if peer is throttled
   - Fix blacklist NPE after config change (ticket #1070)
This commit is contained in:
zzz
2013-10-25 14:09:02 +00:00
parent 102506ebe8
commit ca45194c30
5 changed files with 65 additions and 46 deletions

View File

@ -46,10 +46,11 @@ class ConnThrottler {
* Checks both individual and total. Increments before checking.
*/
boolean shouldThrottle(Hash h) {
// do this first, so we don't increment total if individual throttled
if (_max > 0 && this.counter.increment(h) > _max)
return true;
if (_totalMax > 0 && _currentTotal.incrementAndGet() > _totalMax)
return true;
if (_max > 0)
return this.counter.increment(h) > _max;
return false;
}

View File

@ -395,6 +395,46 @@ class ConnectionManager {
if (from == null)
return "null";
Hash h = from.calculateHash();
// As of 0.9.9, run the blacklist checks BEFORE the port counters,
// so blacklisted dests will not increment the counters and
// possibly trigger total-counter blocks for others.
// if the sig is absent or bad it will be caught later (in CPH)
if (_defaultOptions.isAccessListEnabled() &&
!_defaultOptions.getAccessList().contains(h))
return "not whitelisted";
if (_defaultOptions.isBlacklistEnabled() &&
_defaultOptions.getBlacklist().contains(h))
return "blacklisted";
String hashes = _context.getProperty(PROP_BLACKLIST, "");
if (!_currentBlacklist.equals(hashes)) {
// rebuild _globalBlacklist when property changes
synchronized(_globalBlacklist) {
if (hashes.length() > 0) {
Set<Hash> newSet = new HashSet<Hash>();
StringTokenizer tok = new StringTokenizer(hashes, ",; ");
while (tok.hasMoreTokens()) {
String hashstr = tok.nextToken();
Hash hh = ConvertToHash.getHash(hashstr);
if (hh != null)
newSet.add(hh);
else
_log.error("Bad blacklist entry: " + hashstr);
}
_globalBlacklist.addAll(newSet);
_globalBlacklist.retainAll(newSet);
_currentBlacklist = hashes;
} else {
_globalBlacklist.clear();
_currentBlacklist = "";
}
}
}
if (hashes.length() > 0 && _globalBlacklist.contains(h))
return "blacklisted globally";
String throttled = null;
// always call all 3 to increment all counters
if (_minuteThrottler != null && _minuteThrottler.shouldThrottle(h)) {
@ -439,42 +479,8 @@ class ConnectionManager {
" or total limit of " + _defaultOptions.getMaxTotalConnsPerDay() +
" per day";
}
if (throttled != null)
return throttled;
// if the sig is absent or bad it will be caught later (in CPH)
if (_defaultOptions.isAccessListEnabled() &&
!_defaultOptions.getAccessList().contains(h))
return "not whitelisted";
if (_defaultOptions.isBlacklistEnabled() &&
_defaultOptions.getBlacklist().contains(h))
return "blacklisted";
String hashes = _context.getProperty(PROP_BLACKLIST, "");
if (!_currentBlacklist.equals(hashes)) {
// rebuild _globalBlacklist when property changes
synchronized(_globalBlacklist) {
if (hashes.length() > 0) {
Set<Hash> newSet = new HashSet<Hash>();
StringTokenizer tok = new StringTokenizer(hashes, ",; ");
while (tok.hasMoreTokens()) {
String hashstr = tok.nextToken();
Hash hh = ConvertToHash.getHash(hashstr);
if (hh != null)
newSet.add(hh);
else
_log.error("Bad blacklist entry: " + hashstr);
}
_globalBlacklist.addAll(newSet);
_globalBlacklist.retainAll(newSet);
_currentBlacklist = hashes;
} else {
_globalBlacklist.clear();
_currentBlacklist = "";
}
}
}
if (hashes.length() > 0 && _globalBlacklist.contains(h))
return "blacklisted globally";
return null;
return throttled;
}

View File

@ -754,27 +754,27 @@ class ConnectionOptions extends I2PSocketOptionsImpl {
public Set<Hash> getBlacklist() { return _blackList; }
private void initLists(ConnectionOptions opts) {
_accessListEnabled = opts.isAccessListEnabled();
_blackListEnabled = opts.isBlacklistEnabled();
_accessList = opts.getAccessList();
_blackList = opts.getBlacklist();
_accessListEnabled = opts.isAccessListEnabled();
_blackListEnabled = opts.isBlacklistEnabled();
}
private void initLists(Properties opts) {
_accessListEnabled = getBool(opts, PROP_ENABLE_ACCESS_LIST, false);
_blackListEnabled = getBool(opts, PROP_ENABLE_BLACKLIST, false);
boolean accessListEnabled = getBool(opts, PROP_ENABLE_ACCESS_LIST, false);
boolean blackListEnabled = getBool(opts, PROP_ENABLE_BLACKLIST, false);
// Don't think these would ever be accessed simultaneously,
// but avoid concurrent modification just in case
Set<Hash> accessList, blackList;
if (_accessListEnabled)
if (accessListEnabled)
accessList = new HashSet();
else
accessList = Collections.EMPTY_SET;
if (_blackListEnabled)
if (blackListEnabled)
blackList = new HashSet();
else
blackList = Collections.EMPTY_SET;
if (_accessListEnabled || _blackListEnabled) {
if (accessListEnabled || blackListEnabled) {
String hashes = opts.getProperty(PROP_ACCESS_LIST);
if (hashes == null)
return;
@ -792,6 +792,8 @@ class ConnectionOptions extends I2PSocketOptionsImpl {
}
_accessList = accessList;
_blackList = blackList;
_accessListEnabled = accessListEnabled;
_blackListEnabled = blackListEnabled;
if (_accessListEnabled && _accessList.isEmpty())
error("Connection access list enabled but no valid entries; no peers can connect");
else if (_blackListEnabled && _blackList.isEmpty())