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
This commit is contained in:
@ -47,12 +47,14 @@ public class I2PSnarkUtil {
|
|||||||
private Set _shitlist;
|
private Set _shitlist;
|
||||||
private int _maxUploaders;
|
private int _maxUploaders;
|
||||||
private int _maxUpBW;
|
private int _maxUpBW;
|
||||||
|
private int _maxConnections;
|
||||||
|
|
||||||
public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
|
public static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers";
|
||||||
public static final boolean DEFAULT_USE_OPENTRACKERS = true;
|
public static final boolean DEFAULT_USE_OPENTRACKERS = true;
|
||||||
public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
|
public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers";
|
||||||
public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a";
|
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 DEFAULT_MAX_UP_BW = 8; //KBps
|
||||||
|
public static final int MAX_CONNECTIONS = 16; // per torrent
|
||||||
|
|
||||||
public I2PSnarkUtil(I2PAppContext ctx) {
|
public I2PSnarkUtil(I2PAppContext ctx) {
|
||||||
_context = ctx;
|
_context = ctx;
|
||||||
@ -64,6 +66,7 @@ public class I2PSnarkUtil {
|
|||||||
_configured = false;
|
_configured = false;
|
||||||
_maxUploaders = Snark.MAX_TOTAL_UPLOADERS;
|
_maxUploaders = Snark.MAX_TOTAL_UPLOADERS;
|
||||||
_maxUpBW = DEFAULT_MAX_UP_BW;
|
_maxUpBW = DEFAULT_MAX_UP_BW;
|
||||||
|
_maxConnections = MAX_CONNECTIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,7 +90,9 @@ public class I2PSnarkUtil {
|
|||||||
public boolean configured() { return _configured; }
|
public boolean configured() { return _configured; }
|
||||||
|
|
||||||
public void setI2CPConfig(String i2cpHost, int i2cpPort, Map opts) {
|
public void setI2CPConfig(String i2cpHost, int i2cpPort, Map opts) {
|
||||||
|
if (i2cpHost != null)
|
||||||
_i2cpHost = i2cpHost;
|
_i2cpHost = i2cpHost;
|
||||||
|
if (i2cpPort > 0)
|
||||||
_i2cpPort = i2cpPort;
|
_i2cpPort = i2cpPort;
|
||||||
if (opts != null)
|
if (opts != null)
|
||||||
_opts.putAll(opts);
|
_opts.putAll(opts);
|
||||||
@ -104,6 +109,11 @@ public class I2PSnarkUtil {
|
|||||||
_configured = true;
|
_configured = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMaxConnections(int limit) {
|
||||||
|
_maxConnections = limit;
|
||||||
|
_configured = true;
|
||||||
|
}
|
||||||
|
|
||||||
public String getI2CPHost() { return _i2cpHost; }
|
public String getI2CPHost() { return _i2cpHost; }
|
||||||
public int getI2CPPort() { return _i2cpPort; }
|
public int getI2CPPort() { return _i2cpPort; }
|
||||||
public Map getI2CPOptions() { return _opts; }
|
public Map getI2CPOptions() { return _opts; }
|
||||||
@ -112,6 +122,7 @@ public class I2PSnarkUtil {
|
|||||||
public boolean getEepProxySet() { return _shouldProxy; }
|
public boolean getEepProxySet() { return _shouldProxy; }
|
||||||
public int getMaxUploaders() { return _maxUploaders; }
|
public int getMaxUploaders() { return _maxUploaders; }
|
||||||
public int getMaxUpBW() { return _maxUpBW; }
|
public int getMaxUpBW() { return _maxUpBW; }
|
||||||
|
public int getMaxConnections() { return _maxConnections; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to the router, if we aren't already
|
* Connect to the router, if we aren't already
|
||||||
|
@ -44,7 +44,6 @@ public class PeerCoordinator implements PeerListener
|
|||||||
|
|
||||||
// package local for access by CheckDownLoadersTask
|
// package local for access by CheckDownLoadersTask
|
||||||
final static long CHECK_PERIOD = 40*1000; // 40 seconds
|
final static long CHECK_PERIOD = 40*1000; // 40 seconds
|
||||||
final static int MAX_CONNECTIONS = 16;
|
|
||||||
final static int MAX_UPLOADERS = 6;
|
final static int MAX_UPLOADERS = 6;
|
||||||
|
|
||||||
// Approximation of the number of current uploaders.
|
// Approximation of the number of current uploaders.
|
||||||
@ -237,7 +236,7 @@ public class PeerCoordinator implements PeerListener
|
|||||||
{
|
{
|
||||||
synchronized(peers)
|
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.
|
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
|
// 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))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("Already at MAX_CONNECTIONS in connected() with peer: " + peer);
|
_log.warn("Already at MAX_CONNECTIONS in connected() with peer: " + peer);
|
||||||
@ -351,7 +350,7 @@ public class PeerCoordinator implements PeerListener
|
|||||||
peersize = peers.size();
|
peersize = peers.size();
|
||||||
// This isn't a strict limit, as we may have several pending connections;
|
// This isn't a strict limit, as we may have several pending connections;
|
||||||
// thus there is an additional check in connected()
|
// 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
|
// Check if we already have this peer before we build the connection
|
||||||
Peer old = peerIDInList(peer.getPeerID(), peers);
|
Peer old = peerIDInList(peer.getPeerID(), peers);
|
||||||
need_more = need_more && ((old == null) || (old.getInactiveTime() > 8*60*1000));
|
need_more = need_more && ((old == null) || (old.getInactiveTime() > 8*60*1000));
|
||||||
@ -379,7 +378,7 @@ public class PeerCoordinator implements PeerListener
|
|||||||
if (peer.isConnected())
|
if (peer.isConnected())
|
||||||
_log.info("Add peer already connected: " + peer);
|
_log.info("Add peer already connected: " + peer);
|
||||||
else
|
else
|
||||||
_log.info("Connections: " + peersize + "/" + MAX_CONNECTIONS
|
_log.info("Connections: " + peersize + "/" + _util.getMaxConnections()
|
||||||
+ " not accepting extra peer: " + peer);
|
+ " not accepting extra peer: " + peer);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -28,6 +28,7 @@ import java.io.InputStream;
|
|||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
@ -35,6 +36,7 @@ import java.util.Timer;
|
|||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.router.client.ClientManagerFacadeImpl;
|
||||||
import net.i2p.client.streaming.I2PServerSocket;
|
import net.i2p.client.streaming.I2PServerSocket;
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
import net.i2p.util.I2PThread;
|
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 String torrent;
|
||||||
public MetaInfo meta;
|
public MetaInfo meta;
|
||||||
public Storage storage;
|
public Storage storage;
|
||||||
@ -254,10 +257,35 @@ public class Snark
|
|||||||
this(util, torrent, ip, user_port, slistener, clistener, null, null, null, true, ".");
|
this(util, torrent, ip, user_port, slistener, clistener, null, null, null, true, ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** single torrent */
|
/** single torrent - via router */
|
||||||
Snark(I2PAppContext ctx, String torrent, String ip, int user_port,
|
public Snark(I2PAppContext ctx, Properties opts, String torrent,
|
||||||
StorageListener slistener, CoordinatorListener clistener) {
|
StorageListener slistener, boolean start, String rootDir) {
|
||||||
this(new I2PSnarkUtil(ctx), torrent, ip, user_port, slistener, clistener, null, null, null, true, ".");
|
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 */
|
/** multitorrent */
|
||||||
@ -523,6 +551,8 @@ public class Snark
|
|||||||
}
|
}
|
||||||
if (pc != null && _peerCoordinatorSet != null)
|
if (pc != null && _peerCoordinatorSet != null)
|
||||||
_peerCoordinatorSet.remove(pc);
|
_peerCoordinatorSet.remove(pc);
|
||||||
|
if (_peerCoordinatorSet == null)
|
||||||
|
_util.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Snark parseArguments(String[] args)
|
static Snark parseArguments(String[] args)
|
||||||
|
@ -32,7 +32,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
/** map of (canonical) filename to Snark instance (unsynchronized) */
|
/** map of (canonical) filename to Snark instance (unsynchronized) */
|
||||||
private Map _snarks;
|
private Map _snarks;
|
||||||
private Object _addSnarkLock;
|
private Object _addSnarkLock;
|
||||||
private String _configFile;
|
private String _configFile = "i2psnark.config";
|
||||||
private Properties _config;
|
private Properties _config;
|
||||||
private I2PAppContext _context;
|
private I2PAppContext _context;
|
||||||
private Log _log;
|
private Log _log;
|
||||||
@ -67,9 +67,15 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
_log = _context.logManager().getLog(SnarkManager.class);
|
_log = _context.logManager().getLog(SnarkManager.class);
|
||||||
_messages = new ArrayList(16);
|
_messages = new ArrayList(16);
|
||||||
_util = new I2PSnarkUtil(_context);
|
_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();
|
_peerCoordinatorSet = new PeerCoordinatorSet();
|
||||||
_connectionAcceptor = new ConnectionAcceptor(_util);
|
_connectionAcceptor = new ConnectionAcceptor(_util);
|
||||||
loadConfig("i2psnark.config");
|
|
||||||
int minutes = getStartupDelayMinutes();
|
int minutes = getStartupDelayMinutes();
|
||||||
_messages.add("Adding torrents in " + minutes + (minutes == 1 ? " minute" : " minutes"));
|
_messages.add("Adding torrents in " + minutes + (minutes == 1 ? " minute" : " minutes"));
|
||||||
I2PAppThread monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor");
|
I2PAppThread monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor");
|
||||||
@ -114,10 +120,12 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
return new File(dir);
|
return new File(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** null to set initial defaults */
|
||||||
public void loadConfig(String filename) {
|
public void loadConfig(String filename) {
|
||||||
_configFile = filename;
|
|
||||||
if (_config == null)
|
if (_config == null)
|
||||||
_config = new Properties();
|
_config = new Properties();
|
||||||
|
if (filename != null) {
|
||||||
|
_configFile = filename;
|
||||||
File cfg = new File(filename);
|
File cfg = new File(filename);
|
||||||
if (cfg.exists()) {
|
if (cfg.exists()) {
|
||||||
try {
|
try {
|
||||||
@ -126,6 +134,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
_log.error("Error loading I2PSnark config '" + filename + "'", ioe);
|
_log.error("Error loading I2PSnark config '" + filename + "'", ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// now add sane defaults
|
// now add sane defaults
|
||||||
if (!_config.containsKey(PROP_I2CP_HOST))
|
if (!_config.containsKey(PROP_I2CP_HOST))
|
||||||
_config.setProperty(PROP_I2CP_HOST, "localhost");
|
_config.setProperty(PROP_I2CP_HOST, "localhost");
|
||||||
|
@ -55,6 +55,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
|||||||
if ( (configFile == null) || (configFile.trim().length() <= 0) )
|
if ( (configFile == null) || (configFile.trim().length() <= 0) )
|
||||||
configFile = "i2psnark.config";
|
configFile = "i2psnark.config";
|
||||||
_manager.loadConfig(configFile);
|
_manager.loadConfig(configFile);
|
||||||
|
_manager.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
Reference in New Issue
Block a user