From c0c95827efd0689681d0ca3a263dea4f2d563548 Mon Sep 17 00:00:00 2001
From: zab2 <zab2@mail.i2p>
Date: Fri, 29 Mar 2019 16:27:10 +0000
Subject: [PATCH] add logic to start and stop filter timers

---
 .../net/i2p/i2ptunnel/I2PTunnelServer.java    | 17 +++++++++--
 .../i2p/i2ptunnel/access/AccessFilter.java    | 30 ++++++++++++-------
 .../i2p/i2ptunnel/access/FilterFactory.java   | 11 +++----
 .../streaming/StatefulConnectionFilter.java   | 19 ++++++++++++
 4 files changed, 57 insertions(+), 20 deletions(-)
 create mode 100644 apps/ministreaming/java/src/net/i2p/client/streaming/StatefulConnectionFilter.java

diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java
index ecbc9af606..b7d0015eae 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelServer.java
@@ -40,6 +40,7 @@ import net.i2p.client.streaming.I2PSocketManager;
 import net.i2p.client.streaming.I2PSocketManagerFactory;
 import net.i2p.client.streaming.RouterRestartException;
 import net.i2p.client.streaming.IncomingConnectionFilter;
+import net.i2p.client.streaming.StatefulConnectionFilter;
 import net.i2p.crypto.SigType;
 import net.i2p.data.Base64;
 import net.i2p.data.Hash;
@@ -97,6 +98,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
     private int DEFAULT_LOCALPORT = 4488;
     protected int localPort = DEFAULT_LOCALPORT;
 
+    private volatile StatefulConnectionFilter _filter;
+
     /**
      *  Non-blocking
      *
@@ -223,16 +226,18 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
             }
         }
 
-        IncomingConnectionFilter filter = IncomingConnectionFilter.ALLOW;
         if (getTunnel().filterDefinition != null) {
             File filterDefinition = new File(getTunnel().filterDefinition);
             I2PAppContext context = getTunnel().getContext();
             try {
-                filter = FilterFactory.createFilter(context, filterDefinition, this);
+                _filter = FilterFactory.createFilter(context, filterDefinition);
             } catch (IOException | InvalidDefinitionException bad) {
                 throw new IllegalArgumentException("Can't create socket manager", bad);
             }
-        } 
+        }
+
+        IncomingConnectionFilter filter = _filter == null ? IncomingConnectionFilter.ALLOW : _filter;
+
         try {
             I2PSocketManager rv = I2PSocketManagerFactory.createDisconnectedManager(privData, getTunnel().host,
                                                                                     portNum, props, filter);
@@ -376,6 +381,9 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
      */
     public synchronized void startRunning() {
         connectManager();
+        StatefulConnectionFilter filter = _filter;
+        if (filter != null)
+            filter.start();
         // prevent JVM exit when running outside the router
         boolean isDaemon = getTunnel().getContext().isRouterContext();
         Thread t = new I2PAppThread(this, "Server " + remoteHost + ':' + remotePort, isDaemon);
@@ -430,6 +438,9 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
         if (task != null) {
             task.close(forced);
         }
+        StatefulConnectionFilter filter = _filter;
+        if (filter != null)
+            filter.stop();
         synchronized (lock) {
             if (!forced && sockMgr.listSockets().size() != 0) {
                 l.log("There are still active connections!");
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/access/AccessFilter.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/access/AccessFilter.java
index eff55e38d5..b8c3a3dfd0 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/access/AccessFilter.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/access/AccessFilter.java
@@ -5,6 +5,7 @@ import java.util.HashMap;
 import java.util.Set;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import java.io.File;
 import java.io.FileReader;
@@ -19,8 +20,7 @@ import net.i2p.util.Log;
 import net.i2p.util.SecureFileOutputStream;
 import net.i2p.data.Destination;
 import net.i2p.data.Hash;
-import net.i2p.i2ptunnel.I2PTunnelTask;
-import net.i2p.client.streaming.IncomingConnectionFilter;
+import net.i2p.client.streaming.StatefulConnectionFilter;
 
 /**
  * A filter for incoming connections which can be configured
@@ -36,14 +36,15 @@ import net.i2p.client.streaming.IncomingConnectionFilter;
  *
  * @since 0.9.40
  */
-class AccessFilter implements IncomingConnectionFilter {
+class AccessFilter implements StatefulConnectionFilter {
 
     private static final long PURGE_INTERVAL = 1000;
     private static final long SYNC_INTERVAL = 10 * 1000;
 
     private final FilterDefinition definition;
     private final I2PAppContext context;
-    private final I2PTunnelTask task;
+
+    private final AtomicBoolean timersRunning = new AtomicBoolean();
 
     /**
      * Trackers for known destinations defined in access lists
@@ -59,16 +60,25 @@ class AccessFilter implements IncomingConnectionFilter {
      * @param definition definition of this filter
      * @param task the task to query for liveness of the tunnel
      */
-    AccessFilter(I2PAppContext context, FilterDefinition definition, I2PTunnelTask task) 
+    AccessFilter(I2PAppContext context, FilterDefinition definition) 
             throws IOException {
         this.context = context;
         this.definition = definition;
-        this.task = task;
 
         reload();
+    }
 
-        new Purger();
-        new Syncer();
+    @Override
+    public void start() {
+        if (timersRunning.compareAndSet(false, true)) {
+            new Purger();
+            new Syncer();
+        }
+    }
+
+    @Override
+    public void stop() {
+        timersRunning.set(false);
     }
 
     @Override
@@ -169,7 +179,7 @@ class AccessFilter implements IncomingConnectionFilter {
             super(context.simpleTimer2(), PURGE_INTERVAL);
         }
         public void timeReached() {
-            if (!task.isOpen()) {
+            if (!timersRunning.get()) {
                 synchronized(knownDests) {
                     knownDests.clear();
                 }
@@ -188,7 +198,7 @@ class AccessFilter implements IncomingConnectionFilter {
             super(context.simpleTimer2(), SYNC_INTERVAL);
         }
         public void timeReached() {
-            if (!task.isOpen())
+            if (!timersRunning.get())
                 return;
             try {
                 record();
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/access/FilterFactory.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/access/FilterFactory.java
index 54267d6e09..e7c84ea55c 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/access/FilterFactory.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/access/FilterFactory.java
@@ -9,8 +9,7 @@ import java.util.List;
 import java.util.ArrayList;
 
 import net.i2p.I2PAppContext;
-import net.i2p.i2ptunnel.I2PTunnelTask;
-import net.i2p.client.streaming.IncomingConnectionFilter;
+import net.i2p.client.streaming.StatefulConnectionFilter;
 
 /**
  * Factory for incoming connection filters.  Only public class in this package.
@@ -25,11 +24,9 @@ public class FilterFactory {
      *
      * @param context the context this is running in
      * @param definition file containing the filter definition
-     * @param task the I2PTunnelTask instance to query for liveness
      */
-    public static IncomingConnectionFilter createFilter(I2PAppContext context, 
-                                                        File definition,
-                                                        I2PTunnelTask task)
+    public static StatefulConnectionFilter createFilter(I2PAppContext context, 
+                                                        File definition)
         throws IOException, InvalidDefinitionException {
         List<String> linesList = new ArrayList<String>();
 
@@ -50,6 +47,6 @@ public class FilterFactory {
         }
 
         FilterDefinition parsedDefinition = DefinitionParser.parse(linesList.toArray(new String[0]));
-        return new AccessFilter(context, parsedDefinition, task);
+        return new AccessFilter(context, parsedDefinition);
     }
 }
diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/StatefulConnectionFilter.java b/apps/ministreaming/java/src/net/i2p/client/streaming/StatefulConnectionFilter.java
new file mode 100644
index 0000000000..bb9ec065cd
--- /dev/null
+++ b/apps/ministreaming/java/src/net/i2p/client/streaming/StatefulConnectionFilter.java
@@ -0,0 +1,19 @@
+package net.i2p.client.streaming;
+
+/**
+ * A ConnectionFilter that may hold state, can be started and stopped
+ * @since 0.9.40
+ */
+public interface StatefulConnectionFilter extends IncomingConnectionFilter {
+
+    /**
+     * Tells this filter to start
+     */ 
+    public void start();
+
+    /**
+     * Tells this filter to stop and release any resources
+     */
+    public void stop();
+
+}
-- 
GitLab