From 8633ef9513da87e4457e6374cd16895723dddb26 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Wed, 12 Sep 2012 21:52:12 +0000
Subject: [PATCH]   * Streaming: Don't send a RST to an hour/day limited peer, 
    or blacklisted, or non-whitelisted, to not waste outbound bandwidth

---
 .../i2p/client/streaming/ConnThrottler.java   | 14 ++++++++++++-
 .../client/streaming/ConnectionManager.java   | 21 ++++++++++++++++++-
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/apps/streaming/java/src/net/i2p/client/streaming/ConnThrottler.java b/apps/streaming/java/src/net/i2p/client/streaming/ConnThrottler.java
index baa3d52e39..69f0bb8571 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/ConnThrottler.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/ConnThrottler.java
@@ -38,7 +38,9 @@ class ConnThrottler {
         SimpleScheduler.getInstance().addPeriodicEvent(new Cleaner(), period);
     }
 
-    /** increments before checking */
+    /**
+     *  Checks both individual and total. Increments before checking.
+     */
     boolean shouldThrottle(Hash h) {
         if (_totalMax > 0 && _currentTotal.incrementAndGet() > _totalMax)
             return true;
@@ -47,6 +49,16 @@ class ConnThrottler {
         return false;
     }
 
+    /**
+     *  Checks individual count only. Does not increment.
+     *  @since 0.9.3
+     */
+    boolean isThrottled(Hash h) {
+        if (_max > 0)
+            return this.counter.count(h) > _max;
+        return false;
+    }
+
     private class Cleaner implements SimpleTimer.TimedEvent {
         public void timeReached() {
             if (_totalMax > 0)
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionManager.java b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionManager.java
index 885b72cdc9..3547b55440 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/ConnectionManager.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/ConnectionManager.java
@@ -202,7 +202,26 @@ class ConnectionManager {
         _context.statManager().addRateData("stream.receiveActive", active, total);
         
         if (reject) {
-            PacketLocal reply = new PacketLocal(_context, synPacket.getOptionalFrom());
+            Destination from = synPacket.getOptionalFrom();
+            if (from == null)
+                return null;
+            if (_dayThrottler != null || _hourThrottler != null) {
+                Hash h = from.calculateHash();
+                if ((_hourThrottler != null && _hourThrottler.isThrottled(h)) ||
+                    (_dayThrottler != null && _dayThrottler.isThrottled(h)) ||
+                    (_defaultOptions.isAccessListEnabled() && !_defaultOptions.getAccessList().contains(h)) ||
+                    (_defaultOptions.isBlacklistEnabled() && _defaultOptions.getBlacklist().contains(h))) {
+                    // A signed RST packet + ElGamal + session tags is fairly expensive, so
+                    // once the hour/day limit is hit for a particular peer, don't even send it.
+                    // Ditto for blacklist / whitelist
+                    // This is a tradeoff, because it will keep retransmitting the SYN for a while,
+                    // thus more inbound, but let's not spend several KB on the outbound.
+                    if (_log.shouldLog(Log.INFO))
+                        _log.info("Dropping RST to " + h);
+                    return null;
+                }
+            }
+            PacketLocal reply = new PacketLocal(_context, from);
             reply.setFlag(Packet.FLAG_RESET);
             reply.setFlag(Packet.FLAG_SIGNATURE_INCLUDED);
             reply.setAckThrough(synPacket.getSequenceNum());
-- 
GitLab