From 0ff816742550269b3316edf6a7df8112d95a8b79 Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Tue, 18 Nov 2008 02:18:23 +0000
Subject: [PATCH] i2psnark:     - Don't create SnarkManager instance until
 first call,       so it doesn't create the i2psnark dir, read the config,    
   etc., for single Snark instances.     - Don't read i2psnark.config twice;
 fix setting       i2psnark.dir     - More Snark constructor changes for
 calling from router     - Make max connections per torrent configurable

---
 .../src/org/klomp/snark/I2PSnarkUtil.java     | 15 +++++++-
 .../src/org/klomp/snark/PeerCoordinator.java  |  9 ++---
 .../java/src/org/klomp/snark/Snark.java       | 38 +++++++++++++++++--
 .../src/org/klomp/snark/SnarkManager.java     | 29 +++++++++-----
 .../org/klomp/snark/web/I2PSnarkServlet.java  |  1 +
 5 files changed, 71 insertions(+), 21 deletions(-)

diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
index bdfc056efd..7b674b0a05 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java
@@ -47,12 +47,14 @@ public class I2PSnarkUtil {
     private Set _shitlist;
     private int _maxUploaders;
     private int _maxUpBW;
+    private int _maxConnections;
     
     public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
     public static final boolean DEFAULT_USE_OPENTRACKERS = true;
     public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
     public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a";
     public static final int DEFAULT_MAX_UP_BW = 8;  //KBps
+    public static final int MAX_CONNECTIONS = 16; // per torrent
 
     public I2PSnarkUtil(I2PAppContext ctx) {
         _context = ctx;
@@ -64,6 +66,7 @@ public class I2PSnarkUtil {
         _configured = false;
         _maxUploaders = Snark.MAX_TOTAL_UPLOADERS;
         _maxUpBW = DEFAULT_MAX_UP_BW;
+        _maxConnections = MAX_CONNECTIONS;
     }
     
     /**
@@ -87,8 +90,10 @@ public class I2PSnarkUtil {
     public boolean configured() { return _configured; }
     
     public void setI2CPConfig(String i2cpHost, int i2cpPort, Map opts) {
-        _i2cpHost = i2cpHost;
-        _i2cpPort = i2cpPort;
+        if (i2cpHost != null)
+            _i2cpHost = i2cpHost;
+        if (i2cpPort > 0)
+            _i2cpPort = i2cpPort;
         if (opts != null)
             _opts.putAll(opts);
         _configured = true;
@@ -104,6 +109,11 @@ public class I2PSnarkUtil {
         _configured = true;
     }
     
+    public void setMaxConnections(int limit) {
+        _maxConnections = limit;
+        _configured = true;
+    }
+    
     public String getI2CPHost() { return _i2cpHost; }
     public int getI2CPPort() { return _i2cpPort; }
     public Map getI2CPOptions() { return _opts; }
@@ -112,6 +122,7 @@ public class I2PSnarkUtil {
     public boolean getEepProxySet() { return _shouldProxy; }
     public int getMaxUploaders() { return _maxUploaders; }
     public int getMaxUpBW() { return _maxUpBW; }
+    public int getMaxConnections() { return _maxConnections; }
     
     /**
      * Connect to the router, if we aren't already
diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java
index b54cbdafa4..ba5597e591 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java
@@ -44,7 +44,6 @@ public class PeerCoordinator implements PeerListener
 
   // package local for access by CheckDownLoadersTask
   final static long CHECK_PERIOD = 40*1000; // 40 seconds
-  final static int MAX_CONNECTIONS = 16;
   final static int MAX_UPLOADERS = 6;
 
   // Approximation of the number of current uploaders.
@@ -237,7 +236,7 @@ public class PeerCoordinator implements PeerListener
   {
     synchronized(peers)
       {
-        return !halted && peers.size() < MAX_CONNECTIONS;
+        return !halted && peers.size() < _util.getMaxConnections();
       }
   }
   
@@ -295,7 +294,7 @@ public class PeerCoordinator implements PeerListener
             peer.disconnect(false); // Don't deregister this connection/peer.
           }
         // This is already checked in addPeer() but we could have gone over the limit since then
-        else if (peers.size() >= MAX_CONNECTIONS)
+        else if (peers.size() >= _util.getMaxConnections())
           {
             if (_log.shouldLog(Log.WARN))
               _log.warn("Already at MAX_CONNECTIONS in connected() with peer: " + peer);
@@ -351,7 +350,7 @@ public class PeerCoordinator implements PeerListener
         peersize = peers.size();
         // This isn't a strict limit, as we may have several pending connections;
         // thus there is an additional check in connected()
-        need_more = (!peer.isConnected()) && peersize < MAX_CONNECTIONS;
+        need_more = (!peer.isConnected()) && peersize < _util.getMaxConnections();
         // Check if we already have this peer before we build the connection
         Peer old = peerIDInList(peer.getPeerID(), peers);
         need_more = need_more && ((old == null) || (old.getInactiveTime() > 8*60*1000));
@@ -379,7 +378,7 @@ public class PeerCoordinator implements PeerListener
       if (peer.isConnected())
         _log.info("Add peer already connected: " + peer);
       else
-        _log.info("Connections: " + peersize + "/" + MAX_CONNECTIONS
+        _log.info("Connections: " + peersize + "/" + _util.getMaxConnections()
                   + " not accepting extra peer: " + peer);
     }
     return false;
diff --git a/apps/i2psnark/java/src/org/klomp/snark/Snark.java b/apps/i2psnark/java/src/org/klomp/snark/Snark.java
index fdb334d3d3..f10ef41d33 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/Snark.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/Snark.java
@@ -28,6 +28,7 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import java.util.Random;
 import java.util.StringTokenizer;
@@ -35,6 +36,7 @@ import java.util.Timer;
 import java.util.TimerTask;
 
 import net.i2p.I2PAppContext;
+import net.i2p.router.client.ClientManagerFacadeImpl;
 import net.i2p.client.streaming.I2PServerSocket;
 import net.i2p.data.Destination;
 import net.i2p.util.I2PThread;
@@ -235,6 +237,7 @@ public class Snark
       }
   }
 
+  public static final String PROP_MAX_CONNECTIONS = "i2psnark.maxConnections";
   public String torrent;
   public MetaInfo meta;
   public Storage storage;
@@ -254,10 +257,35 @@ public class Snark
     this(util, torrent, ip, user_port, slistener, clistener, null, null, null, true, "."); 
   }
 
-  /** single torrent */
-  Snark(I2PAppContext ctx, String torrent, String ip, int user_port,
-        StorageListener slistener, CoordinatorListener clistener) { 
-    this(new I2PSnarkUtil(ctx), torrent, ip, user_port, slistener, clistener, null, null, null, true, "."); 
+  /** single torrent - via router */
+  public Snark(I2PAppContext ctx, Properties opts, String torrent,
+               StorageListener slistener, boolean start, String rootDir) { 
+    this(new I2PSnarkUtil(ctx), torrent, null, -1, slistener, null, null, null, null, false, rootDir);
+    String host = opts.getProperty(ClientManagerFacadeImpl.PROP_CLIENT_HOST);
+    int port = 0;
+    String s = opts.getProperty(ClientManagerFacadeImpl.PROP_CLIENT_PORT);
+    if (s != null) {
+        try {
+             port = Integer.parseInt(s);
+        } catch (NumberFormatException nfe) {}
+    }
+    _util.setI2CPConfig(host, port, opts);
+    s = opts.getProperty(SnarkManager.PROP_UPBW_MAX);
+    if (s != null) {
+        try {
+             int v = Integer.parseInt(s);
+             _util.setMaxUpBW(v);
+        } catch (NumberFormatException nfe) {}
+    }
+    s = opts.getProperty(PROP_MAX_CONNECTIONS);
+    if (s != null) {
+        try {
+             int v = Integer.parseInt(s);
+             _util.setMaxConnections(v);
+        } catch (NumberFormatException nfe) {}
+    }
+    if (start)
+        this.startTorrent();
   }
 
   /** multitorrent */
@@ -523,6 +551,8 @@ public class Snark
     }
     if (pc != null && _peerCoordinatorSet != null)
         _peerCoordinatorSet.remove(pc);
+    if (_peerCoordinatorSet == null)
+        _util.disconnect();
   }
 
   static Snark parseArguments(String[] args)
diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
index 6ae2be6dd5..4b531f6064 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java
@@ -32,7 +32,7 @@ public class SnarkManager implements Snark.CompleteListener {
     /** map of (canonical) filename to Snark instance (unsynchronized) */
     private Map _snarks;
     private Object _addSnarkLock;
-    private String _configFile;
+    private String _configFile = "i2psnark.config";
     private Properties _config;
     private I2PAppContext _context;
     private Log _log;
@@ -67,9 +67,15 @@ public class SnarkManager implements Snark.CompleteListener {
         _log = _context.logManager().getLog(SnarkManager.class);
         _messages = new ArrayList(16);
         _util = new I2PSnarkUtil(_context);
+        loadConfig(null);
+    }
+
+    /** Caller _must_ call loadConfig(file) before this if setting new values
+     *  for i2cp host/port or i2psnark.dir
+     */
+    public void start() {
         _peerCoordinatorSet = new PeerCoordinatorSet();
         _connectionAcceptor = new ConnectionAcceptor(_util);
-        loadConfig("i2psnark.config");
         int minutes = getStartupDelayMinutes();
         _messages.add("Adding torrents in " + minutes + (minutes == 1 ? " minute" : " minutes"));
         I2PAppThread monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor");
@@ -114,17 +120,20 @@ public class SnarkManager implements Snark.CompleteListener {
         return new File(dir); 
     }
     
+    /** null to set initial defaults */
     public void loadConfig(String filename) {
-        _configFile = filename;
         if (_config == null)
             _config = new Properties();
-        File cfg = new File(filename);
-        if (cfg.exists()) {
-            try {
-                DataHelper.loadProps(_config, cfg);
-            } catch (IOException ioe) {
-                _log.error("Error loading I2PSnark config '" + filename + "'", ioe);
-            }
+        if (filename != null) {
+            _configFile = filename;
+            File cfg = new File(filename);
+            if (cfg.exists()) {
+                try {
+                    DataHelper.loadProps(_config, cfg);
+                } catch (IOException ioe) {
+                   _log.error("Error loading I2PSnark config '" + filename + "'", ioe);
+                }
+            } 
         } 
         // now add sane defaults
         if (!_config.containsKey(PROP_I2CP_HOST))
diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
index c4baa45cd2..e276ccd88f 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
@@ -55,6 +55,7 @@ public class I2PSnarkServlet extends HttpServlet {
         if ( (configFile == null) || (configFile.trim().length() <= 0) )
             configFile = "i2psnark.config";
         _manager.loadConfig(configFile);
+        _manager.start();
     }
     
     public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-- 
GitLab