diff --git a/core/src/main/java/com/muwire/core/util/MessageThrottle.java b/core/src/main/java/com/muwire/core/util/MessageThrottle.java new file mode 100644 index 00000000..53867872 --- /dev/null +++ b/core/src/main/java/com/muwire/core/util/MessageThrottle.java @@ -0,0 +1,33 @@ +package com.muwire.core.util; + +public class MessageThrottle { + + private final long interval; + private final int allowed; + + private final long[] timestamps; + private long lastMsg; + private int idx; + + public MessageThrottle(long interval, int allowed) { + this.interval = interval; + this.allowed = allowed; + this.timestamps = new long[allowed]; + } + + long lastMsg() { + return lastMsg; + } + + public boolean allow(long now) { + lastMsg = now; + final long previous = timestamps[idx]; + if (previous == 0 || now - previous > interval) { + timestamps[idx++] = now; + if (idx == allowed) + idx = 0; + return true; + } + return false; + } +} diff --git a/core/src/main/java/com/muwire/core/util/SenderThrottle.java b/core/src/main/java/com/muwire/core/util/SenderThrottle.java new file mode 100644 index 00000000..a8e7a9d2 --- /dev/null +++ b/core/src/main/java/com/muwire/core/util/SenderThrottle.java @@ -0,0 +1,40 @@ +package com.muwire.core.util; + +import com.muwire.core.Persona; +import net.i2p.util.UIMessages; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class SenderThrottle { + private final long interval; + private final int allowed; + + private final Map throttleMap = + new HashMap<>(); + + public SenderThrottle(long interval, int allowed) { + this.interval = interval; + this.allowed = allowed; + } + + public boolean allow(long now, Persona sender) { + MessageThrottle throttle = throttleMap.computeIfAbsent(sender, + p -> {return new MessageThrottle(interval, allowed);}); + return throttle.allow(now); + } + + public int clear(long now) { + int rv = 0; + for (Iterator> iterator = throttleMap.entrySet().iterator(); + iterator.hasNext();) { + Map.Entry entry = iterator.next(); + if (now - entry.getValue().lastMsg() > interval) { + iterator.remove(); + rv++; + } + } + return rv; + } +} diff --git a/core/src/test/groovy/com/muwire/core/util/MessageThrottleTest.groovy b/core/src/test/groovy/com/muwire/core/util/MessageThrottleTest.groovy new file mode 100644 index 00000000..0349c9d2 --- /dev/null +++ b/core/src/test/groovy/com/muwire/core/util/MessageThrottleTest.groovy @@ -0,0 +1,27 @@ +package com.muwire.core.util + +import org.junit.Test + +class MessageThrottleTest { + + @Test + public void testThrottleOne() { + def throttle = new MessageThrottle(100, 1) + assert throttle.allow(1) + assert !throttle.allow(2) + assert !throttle.allow(10) + assert throttle.allow(102) + } + + @Test + public void testAllowThree() { + def throttle = new MessageThrottle(100, 3) + assert throttle.allow(1) + assert throttle.allow(2) + assert throttle.allow(3) + + assert !throttle.allow(101) + + assert throttle.allow(102) + } +} diff --git a/core/src/test/groovy/com/muwire/core/util/SenderThrottleTest.groovy b/core/src/test/groovy/com/muwire/core/util/SenderThrottleTest.groovy new file mode 100644 index 00000000..7dfb92e9 --- /dev/null +++ b/core/src/test/groovy/com/muwire/core/util/SenderThrottleTest.groovy @@ -0,0 +1,32 @@ +package com.muwire.core.util + +import com.muwire.core.Personas +import org.junit.Test + +class SenderThrottleTest { + + + private static Personas personas = new Personas() + + @Test + public void testSenders() { + def throttle = new SenderThrottle(100, 1) + assert throttle.allow(1, personas.persona1) + assert throttle.allow(1, personas.persona2) + + assert !throttle.allow(2, personas.persona1) + assert !throttle.allow(2, personas.persona2) + } + + @Test + public void testClear() { + def throttle = new SenderThrottle(100, 1) + + assert throttle.clear(1) == 0 + + throttle.allow(1, personas.persona1) + + assert throttle.clear(1) == 0 + assert throttle.clear( 102) == 1 + } +}