i2psnark:
- Remove static instances of I2PSnarkUtil, ConnectionAcceptor, and PeerCoordinatorSet - Convert static classes in Snark to listeners - Fix Snark to work in single torrent mode again - Should now work with multiple single Snarks
This commit is contained in:
@ -36,17 +36,16 @@ import net.i2p.util.Log;
|
||||
*/
|
||||
public class ConnectionAcceptor implements Runnable
|
||||
{
|
||||
private static final ConnectionAcceptor _instance = new ConnectionAcceptor();
|
||||
public static final ConnectionAcceptor instance() { return _instance; }
|
||||
private Log _log = new Log(ConnectionAcceptor.class);
|
||||
private I2PServerSocket serverSocket;
|
||||
private PeerAcceptor peeracceptor;
|
||||
private Thread thread;
|
||||
private I2PSnarkUtil _util;
|
||||
|
||||
private boolean stop;
|
||||
private boolean socketChanged;
|
||||
|
||||
private ConnectionAcceptor() {}
|
||||
public ConnectionAcceptor(I2PSnarkUtil util) { _util = util; }
|
||||
|
||||
public synchronized void startAccepting(PeerCoordinatorSet set, I2PServerSocket socket) {
|
||||
if (serverSocket != socket) {
|
||||
@ -63,11 +62,12 @@ public class ConnectionAcceptor implements Runnable
|
||||
}
|
||||
}
|
||||
|
||||
public ConnectionAcceptor(I2PServerSocket serverSocket,
|
||||
public ConnectionAcceptor(I2PSnarkUtil util, I2PServerSocket serverSocket,
|
||||
PeerAcceptor peeracceptor)
|
||||
{
|
||||
this.serverSocket = serverSocket;
|
||||
this.peeracceptor = peeracceptor;
|
||||
_util = util;
|
||||
|
||||
socketChanged = false;
|
||||
stop = false;
|
||||
@ -78,7 +78,7 @@ public class ConnectionAcceptor implements Runnable
|
||||
|
||||
public void halt()
|
||||
{
|
||||
if (true) throw new RuntimeException("wtf");
|
||||
if (stop) return;
|
||||
stop = true;
|
||||
|
||||
I2PServerSocket ss = serverSocket;
|
||||
@ -95,7 +95,7 @@ public class ConnectionAcceptor implements Runnable
|
||||
}
|
||||
|
||||
public void restart() {
|
||||
serverSocket = I2PSnarkUtil.instance().getServerSocket();
|
||||
serverSocket = _util.getServerSocket();
|
||||
socketChanged = true;
|
||||
Thread t = thread;
|
||||
if (t != null)
|
||||
@ -116,7 +116,7 @@ public class ConnectionAcceptor implements Runnable
|
||||
socketChanged = false;
|
||||
}
|
||||
while ( (serverSocket == null) && (!stop)) {
|
||||
serverSocket = I2PSnarkUtil.instance().getServerSocket();
|
||||
serverSocket = _util.getServerSocket();
|
||||
if (serverSocket == null)
|
||||
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
|
||||
}
|
||||
@ -129,7 +129,7 @@ public class ConnectionAcceptor implements Runnable
|
||||
if (socketChanged) {
|
||||
continue;
|
||||
} else {
|
||||
I2PServerSocket ss = I2PSnarkUtil.instance().getServerSocket();
|
||||
I2PServerSocket ss = _util.getServerSocket();
|
||||
if (ss != serverSocket) {
|
||||
serverSocket = ss;
|
||||
socketChanged = true;
|
||||
@ -143,13 +143,13 @@ public class ConnectionAcceptor implements Runnable
|
||||
catch (I2PException ioe)
|
||||
{
|
||||
if (!socketChanged) {
|
||||
Snark.debug("Error while accepting: " + ioe, Snark.ERROR);
|
||||
_util.debug("Error while accepting: " + ioe, Snark.ERROR);
|
||||
stop = true;
|
||||
}
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
Snark.debug("Error while accepting: " + ioe, Snark.ERROR);
|
||||
_util.debug("Error while accepting: " + ioe, Snark.ERROR);
|
||||
stop = true;
|
||||
}
|
||||
}
|
||||
@ -161,7 +161,6 @@ public class ConnectionAcceptor implements Runnable
|
||||
}
|
||||
catch (I2PException ignored) { }
|
||||
|
||||
throw new RuntimeException("wtf");
|
||||
}
|
||||
|
||||
private class Handler implements Runnable {
|
||||
|
@ -30,4 +30,8 @@ public interface CoordinatorListener
|
||||
* Called when the PeerCoordinator notices a change in the state of a peer.
|
||||
*/
|
||||
void peerChange(PeerCoordinator coordinator, Peer peer);
|
||||
|
||||
public boolean overUploadLimit(int uploaders);
|
||||
public boolean overUpBWLimit();
|
||||
public boolean overUpBWLimit(long total);
|
||||
}
|
||||
|
@ -28,12 +28,13 @@ import net.i2p.util.SimpleTimer;
|
||||
|
||||
/**
|
||||
* I2P specific helpers for I2PSnark
|
||||
* We use this class as a sort of context for i2psnark
|
||||
* so we can run multiple instances of single Snarks
|
||||
* (but not multiple SnarkManagers, it is still static)
|
||||
*/
|
||||
public class I2PSnarkUtil {
|
||||
private I2PAppContext _context;
|
||||
private Log _log;
|
||||
private static I2PSnarkUtil _instance = new I2PSnarkUtil();
|
||||
public static I2PSnarkUtil instance() { return _instance; }
|
||||
|
||||
private boolean _shouldProxy;
|
||||
private String _proxyHost;
|
||||
@ -53,8 +54,8 @@ public class I2PSnarkUtil {
|
||||
public static final String DEFAULT_OPENTRACKERS = "http://tracker.welterde.i2p/a";
|
||||
public static final int DEFAULT_MAX_UP_BW = 8; //KBps
|
||||
|
||||
private I2PSnarkUtil() {
|
||||
_context = I2PAppContext.getGlobalContext();
|
||||
public I2PSnarkUtil(I2PAppContext ctx) {
|
||||
_context = ctx;
|
||||
_log = _context.logManager().getLog(Snark.class);
|
||||
_opts = new HashMap();
|
||||
setProxy("127.0.0.1", 4444);
|
||||
@ -233,6 +234,28 @@ public class I2PSnarkUtil {
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/** Base64 only - static (no naming service) */
|
||||
static Destination getDestinationFromBase64(String ip) {
|
||||
if (ip == null) return null;
|
||||
if (ip.endsWith(".i2p")) {
|
||||
if (ip.length() < 520)
|
||||
return null;
|
||||
try {
|
||||
return new Destination(ip.substring(0, ip.length()-4)); // sans .i2p
|
||||
} catch (DataFormatException dfe) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return new Destination(ip);
|
||||
} catch (DataFormatException dfe) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Base64 Hash or Hash.i2p or name.i2p using naming service */
|
||||
Destination getDestination(String ip) {
|
||||
if (ip == null) return null;
|
||||
if (ip.endsWith(".i2p")) {
|
||||
@ -308,6 +331,9 @@ public class I2PSnarkUtil {
|
||||
}
|
||||
|
||||
/** hook between snark's logger and an i2p log */
|
||||
void debug(String msg, int snarkDebugLevel) {
|
||||
debug(msg, snarkDebugLevel, null);
|
||||
}
|
||||
void debug(String msg, int snarkDebugLevel, Throwable t) {
|
||||
if (t instanceof OutOfMemoryError) {
|
||||
try { Thread.sleep(100); } catch (InterruptedException ie) {}
|
||||
|
@ -173,7 +173,7 @@ public class Peer implements Comparable
|
||||
* If the given BitField is non-null it is send to the peer as first
|
||||
* message.
|
||||
*/
|
||||
public void runConnection(PeerListener listener, BitField bitfield)
|
||||
public void runConnection(I2PSnarkUtil util, PeerListener listener, BitField bitfield)
|
||||
{
|
||||
if (state != null)
|
||||
throw new IllegalStateException("Peer already started");
|
||||
@ -184,7 +184,7 @@ public class Peer implements Comparable
|
||||
// Do we need to handshake?
|
||||
if (din == null)
|
||||
{
|
||||
sock = I2PSnarkUtil.instance().connect(peerID);
|
||||
sock = util.connect(peerID);
|
||||
_log.debug("Connected to " + peerID + ": " + sock);
|
||||
if ((sock == null) || (sock.isClosed())) {
|
||||
throw new IOException("Unable to reach " + peerID);
|
||||
|
@ -35,9 +35,11 @@ class PeerCheckerTask extends TimerTask
|
||||
private static final long KILOPERSECOND = 1024*(PeerCoordinator.CHECK_PERIOD/1000);
|
||||
|
||||
private final PeerCoordinator coordinator;
|
||||
public I2PSnarkUtil _util;
|
||||
|
||||
PeerCheckerTask(PeerCoordinator coordinator)
|
||||
PeerCheckerTask(I2PSnarkUtil util, PeerCoordinator coordinator)
|
||||
{
|
||||
_util = util;
|
||||
this.coordinator = coordinator;
|
||||
}
|
||||
|
||||
@ -102,8 +104,8 @@ class PeerCheckerTask extends TimerTask
|
||||
peer.setRateHistory(upload, download);
|
||||
peer.resetCounters();
|
||||
|
||||
Snark.debug(peer + ":", Snark.DEBUG);
|
||||
Snark.debug(" ul: " + upload/KILOPERSECOND
|
||||
_util.debug(peer + ":", Snark.DEBUG);
|
||||
_util.debug(" ul: " + upload/KILOPERSECOND
|
||||
+ " dl: " + download/KILOPERSECOND
|
||||
+ " i: " + peer.isInterested()
|
||||
+ " I: " + peer.isInteresting()
|
||||
@ -129,7 +131,7 @@ class PeerCheckerTask extends TimerTask
|
||||
// Check if it still wants pieces from us.
|
||||
if (!peer.isInterested())
|
||||
{
|
||||
Snark.debug("Choke uninterested peer: " + peer,
|
||||
_util.debug("Choke uninterested peer: " + peer,
|
||||
Snark.INFO);
|
||||
peer.setChoking(true);
|
||||
uploaders--;
|
||||
@ -141,7 +143,7 @@ class PeerCheckerTask extends TimerTask
|
||||
}
|
||||
else if (overBWLimitChoke)
|
||||
{
|
||||
Snark.debug("BW limit (" + upload + "/" + uploaded + "), choke peer: " + peer,
|
||||
_util.debug("BW limit (" + upload + "/" + uploaded + "), choke peer: " + peer,
|
||||
Snark.INFO);
|
||||
peer.setChoking(true);
|
||||
uploaders--;
|
||||
@ -155,7 +157,7 @@ class PeerCheckerTask extends TimerTask
|
||||
else if (peer.isInteresting() && peer.isChoked())
|
||||
{
|
||||
// If they are choking us make someone else a downloader
|
||||
Snark.debug("Choke choking peer: " + peer, Snark.DEBUG);
|
||||
_util.debug("Choke choking peer: " + peer, Snark.DEBUG);
|
||||
peer.setChoking(true);
|
||||
uploaders--;
|
||||
coordinator.uploaders--;
|
||||
@ -168,7 +170,7 @@ class PeerCheckerTask extends TimerTask
|
||||
else if (!peer.isInteresting() && !coordinator.completed())
|
||||
{
|
||||
// If they aren't interesting make someone else a downloader
|
||||
Snark.debug("Choke uninteresting peer: " + peer, Snark.DEBUG);
|
||||
_util.debug("Choke uninteresting peer: " + peer, Snark.DEBUG);
|
||||
peer.setChoking(true);
|
||||
uploaders--;
|
||||
coordinator.uploaders--;
|
||||
@ -183,7 +185,7 @@ class PeerCheckerTask extends TimerTask
|
||||
&& download == 0)
|
||||
{
|
||||
// We are downloading but didn't receive anything...
|
||||
Snark.debug("Choke downloader that doesn't deliver:"
|
||||
_util.debug("Choke downloader that doesn't deliver:"
|
||||
+ peer, Snark.DEBUG);
|
||||
peer.setChoking(true);
|
||||
uploaders--;
|
||||
@ -222,7 +224,7 @@ class PeerCheckerTask extends TimerTask
|
||||
|| uploaders > uploadLimit)
|
||||
&& worstDownloader != null)
|
||||
{
|
||||
Snark.debug("Choke worst downloader: " + worstDownloader,
|
||||
_util.debug("Choke worst downloader: " + worstDownloader,
|
||||
Snark.DEBUG);
|
||||
|
||||
worstDownloader.setChoking(true);
|
||||
|
@ -77,13 +77,15 @@ public class PeerCoordinator implements PeerListener
|
||||
private boolean halted = false;
|
||||
|
||||
private final CoordinatorListener listener;
|
||||
public I2PSnarkUtil _util;
|
||||
|
||||
public String trackerProblems = null;
|
||||
public int trackerSeenPeers = 0;
|
||||
|
||||
public PeerCoordinator(byte[] id, MetaInfo metainfo, Storage storage,
|
||||
public PeerCoordinator(I2PSnarkUtil util, byte[] id, MetaInfo metainfo, Storage storage,
|
||||
CoordinatorListener listener, Snark torrent)
|
||||
{
|
||||
_util = util;
|
||||
this.id = id;
|
||||
this.metainfo = metainfo;
|
||||
this.storage = storage;
|
||||
@ -96,7 +98,7 @@ public class PeerCoordinator implements PeerListener
|
||||
// Randomize the first start time so multiple tasks are spread out,
|
||||
// this will help the behavior with global limits
|
||||
Random r = new Random();
|
||||
timer.schedule(new PeerCheckerTask(this), (CHECK_PERIOD / 2) + r.nextInt((int) CHECK_PERIOD), CHECK_PERIOD);
|
||||
timer.schedule(new PeerCheckerTask(_util, this), (CHECK_PERIOD / 2) + r.nextInt((int) CHECK_PERIOD), CHECK_PERIOD);
|
||||
}
|
||||
|
||||
// only called externally from Storage after the double-check fails
|
||||
@ -366,7 +368,7 @@ public class PeerCoordinator implements PeerListener
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
peer.runConnection(listener, bitfield);
|
||||
peer.runConnection(_util, listener, bitfield);
|
||||
}
|
||||
};
|
||||
String threadName = peer.toString();
|
||||
@ -846,7 +848,7 @@ public class PeerCoordinator implements PeerListener
|
||||
*/
|
||||
public int allowedUploaders()
|
||||
{
|
||||
if (Snark.overUploadLimit(uploaders)) {
|
||||
if (listener != null && listener.overUploadLimit(uploaders)) {
|
||||
// if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("Over limit, uploaders was: " + uploaders);
|
||||
return uploaders - 1;
|
||||
@ -858,12 +860,16 @@ public class PeerCoordinator implements PeerListener
|
||||
|
||||
public boolean overUpBWLimit()
|
||||
{
|
||||
return Snark.overUpBWLimit();
|
||||
if (listener != null)
|
||||
return listener.overUpBWLimit();
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean overUpBWLimit(long total)
|
||||
{
|
||||
return Snark.overUpBWLimit(total * 1000 / CHECK_PERIOD);
|
||||
if (listener != null)
|
||||
return listener.overUpBWLimit(total * 1000 / CHECK_PERIOD);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,11 +12,9 @@ import java.util.Set;
|
||||
* from it there too)
|
||||
*/
|
||||
public class PeerCoordinatorSet {
|
||||
private static final PeerCoordinatorSet _instance = new PeerCoordinatorSet();
|
||||
public static final PeerCoordinatorSet instance() { return _instance; }
|
||||
private Set _coordinators;
|
||||
|
||||
private PeerCoordinatorSet() {
|
||||
public PeerCoordinatorSet() {
|
||||
_coordinators = new HashSet();
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ public class PeerID implements Comparable
|
||||
bevalue = (BEValue)m.get("ip");
|
||||
if (bevalue == null)
|
||||
throw new InvalidBEncodingException("ip missing");
|
||||
address = I2PSnarkUtil.instance().getDestination(bevalue.getString());
|
||||
address = I2PSnarkUtil.getDestinationFromBase64(bevalue.getString());
|
||||
if (address == null)
|
||||
throw new InvalidBEncodingException("Invalid destination [" + bevalue.getString() + "]");
|
||||
|
||||
|
@ -34,6 +34,7 @@ import java.util.StringTokenizer;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.client.streaming.I2PServerSocket;
|
||||
import net.i2p.data.Destination;
|
||||
import net.i2p.util.I2PThread;
|
||||
@ -102,7 +103,7 @@ public class Snark
|
||||
public void outOfMemory(OutOfMemoryError err) {
|
||||
try {
|
||||
err.printStackTrace();
|
||||
I2PSnarkUtil.instance().debug("OOM in the snark", Snark.ERROR, err);
|
||||
System.out.println("OOM in the snark" + err);
|
||||
} catch (Throwable t) {
|
||||
System.out.println("OOM in the OOM");
|
||||
}
|
||||
@ -225,7 +226,7 @@ public class Snark
|
||||
}
|
||||
catch(IOException ioe)
|
||||
{
|
||||
debug("ERROR while reading stdin: " + ioe, ERROR);
|
||||
System.out.println("ERROR while reading stdin: " + ioe);
|
||||
}
|
||||
|
||||
// Explicit shutdown.
|
||||
@ -244,22 +245,34 @@ public class Snark
|
||||
public CompleteListener completeListener;
|
||||
public boolean stopped;
|
||||
byte[] id;
|
||||
public I2PSnarkUtil _util;
|
||||
private PeerCoordinatorSet _peerCoordinatorSet;
|
||||
|
||||
Snark(String torrent, String ip, int user_port,
|
||||
/** from main() via parseArguments() single torrent */
|
||||
Snark(I2PSnarkUtil util, String torrent, String ip, int user_port,
|
||||
StorageListener slistener, CoordinatorListener clistener) {
|
||||
this(torrent, ip, user_port, slistener, clistener, null, true, ".");
|
||||
this(util, torrent, ip, user_port, slistener, clistener, null, null, null, true, ".");
|
||||
}
|
||||
public Snark(String torrent, String ip, int user_port,
|
||||
|
||||
/** 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, ".");
|
||||
}
|
||||
|
||||
/** multitorrent */
|
||||
public Snark(I2PSnarkUtil util, String torrent, String ip, int user_port,
|
||||
StorageListener slistener, CoordinatorListener clistener,
|
||||
CompleteListener complistener, boolean start, String rootDir)
|
||||
CompleteListener complistener, PeerCoordinatorSet peerCoordinatorSet,
|
||||
ConnectionAcceptor connectionAcceptor, boolean start, String rootDir)
|
||||
{
|
||||
if (slistener == null)
|
||||
slistener = this;
|
||||
|
||||
//if (clistener == null)
|
||||
// clistener = this;
|
||||
|
||||
completeListener = complistener;
|
||||
_util = util;
|
||||
_peerCoordinatorSet = peerCoordinatorSet;
|
||||
acceptor = connectionAcceptor;
|
||||
|
||||
this.torrent = torrent;
|
||||
this.rootDataDir = rootDir;
|
||||
@ -292,7 +305,7 @@ public class Snark
|
||||
while (i < 20)
|
||||
id[i++] = (byte)random.nextInt(256);
|
||||
|
||||
Snark.debug("My peer id: " + PeerID.idencode(id), Snark.INFO);
|
||||
debug("My peer id: " + PeerID.idencode(id), Snark.INFO);
|
||||
|
||||
int port;
|
||||
IOException lastException = null;
|
||||
@ -301,9 +314,9 @@ public class Snark
|
||||
* If we are starting,
|
||||
* startTorrent() will force a connect.
|
||||
*
|
||||
boolean ok = I2PSnarkUtil.instance().connect();
|
||||
boolean ok = util.connect();
|
||||
if (!ok) fatal("Unable to connect to I2P");
|
||||
I2PServerSocket serversocket = I2PSnarkUtil.instance().getServerSocket();
|
||||
I2PServerSocket serversocket = util.getServerSocket();
|
||||
if (serversocket == null)
|
||||
fatal("Unable to listen for I2P connections");
|
||||
else {
|
||||
@ -324,7 +337,7 @@ public class Snark
|
||||
else
|
||||
{
|
||||
activity = "Getting torrent";
|
||||
File torrentFile = I2PSnarkUtil.instance().get(torrent, 3);
|
||||
File torrentFile = _util.get(torrent, 3);
|
||||
if (torrentFile == null) {
|
||||
fatal("Unable to fetch " + torrent);
|
||||
if (false) return; // never reached - fatal(..) throws
|
||||
@ -348,7 +361,7 @@ public class Snark
|
||||
/*
|
||||
{
|
||||
// Try to create a new metainfo file
|
||||
Snark.debug
|
||||
debug
|
||||
("Trying to create metainfo torrent for '" + torrent + "'",
|
||||
NOTICE);
|
||||
try
|
||||
@ -381,7 +394,7 @@ public class Snark
|
||||
try
|
||||
{
|
||||
activity = "Checking storage";
|
||||
storage = new Storage(meta, slistener);
|
||||
storage = new Storage(_util, meta, slistener);
|
||||
if (completeListener != null) {
|
||||
storage.check(rootDataDir,
|
||||
completeListener.getSavedTorrentTime(this),
|
||||
@ -422,10 +435,10 @@ public class Snark
|
||||
* Start up contacting peers and querying the tracker
|
||||
*/
|
||||
public void startTorrent() {
|
||||
boolean ok = I2PSnarkUtil.instance().connect();
|
||||
boolean ok = _util.connect();
|
||||
if (!ok) fatal("Unable to connect to I2P");
|
||||
if (coordinator == null) {
|
||||
I2PServerSocket serversocket = I2PSnarkUtil.instance().getServerSocket();
|
||||
I2PServerSocket serversocket = _util.getServerSocket();
|
||||
if (serversocket == null)
|
||||
fatal("Unable to listen for I2P connections");
|
||||
else {
|
||||
@ -434,12 +447,20 @@ public class Snark
|
||||
}
|
||||
debug("Starting PeerCoordinator, ConnectionAcceptor, and TrackerClient", NOTICE);
|
||||
activity = "Collecting pieces";
|
||||
coordinator = new PeerCoordinator(id, meta, storage, this, this);
|
||||
PeerCoordinatorSet set = PeerCoordinatorSet.instance();
|
||||
set.add(coordinator);
|
||||
ConnectionAcceptor acceptor = ConnectionAcceptor.instance();
|
||||
acceptor.startAccepting(set, serversocket);
|
||||
trackerclient = new TrackerClient(meta, coordinator);
|
||||
coordinator = new PeerCoordinator(_util, id, meta, storage, this, this);
|
||||
if (_peerCoordinatorSet != null) {
|
||||
// multitorrent
|
||||
_peerCoordinatorSet.add(coordinator);
|
||||
if (acceptor != null) {
|
||||
acceptor.startAccepting(_peerCoordinatorSet, serversocket);
|
||||
} else {
|
||||
// error
|
||||
}
|
||||
} else {
|
||||
// single torrent
|
||||
acceptor = new ConnectionAcceptor(_util, serversocket, new PeerAcceptor(coordinator));
|
||||
}
|
||||
trackerclient = new TrackerClient(_util, meta, coordinator);
|
||||
}
|
||||
|
||||
stopped = false;
|
||||
@ -447,11 +468,12 @@ public class Snark
|
||||
if (coordinator.halted()) {
|
||||
// ok, we have already started and stopped, but the coordinator seems a bit annoying to
|
||||
// restart safely, so lets build a new one to replace the old
|
||||
PeerCoordinatorSet set = PeerCoordinatorSet.instance();
|
||||
set.remove(coordinator);
|
||||
PeerCoordinator newCoord = new PeerCoordinator(coordinator.getID(), coordinator.getMetaInfo(),
|
||||
if (_peerCoordinatorSet != null)
|
||||
_peerCoordinatorSet.remove(coordinator);
|
||||
PeerCoordinator newCoord = new PeerCoordinator(_util, coordinator.getID(), coordinator.getMetaInfo(),
|
||||
coordinator.getStorage(), coordinator.getListener(), this);
|
||||
set.add(newCoord);
|
||||
if (_peerCoordinatorSet != null)
|
||||
_peerCoordinatorSet.add(newCoord);
|
||||
coordinator = newCoord;
|
||||
coordinatorChanged = true;
|
||||
}
|
||||
@ -469,7 +491,7 @@ public class Snark
|
||||
}
|
||||
fatal("Could not reopen storage", ioe);
|
||||
}
|
||||
TrackerClient newClient = new TrackerClient(coordinator.getMetaInfo(), coordinator);
|
||||
TrackerClient newClient = new TrackerClient(_util, coordinator.getMetaInfo(), coordinator);
|
||||
if (!trackerclient.halted())
|
||||
trackerclient.halt();
|
||||
trackerclient = newClient;
|
||||
@ -499,8 +521,8 @@ public class Snark
|
||||
if (changed && completeListener != null)
|
||||
completeListener.updateStatus(this);
|
||||
}
|
||||
if (pc != null)
|
||||
PeerCoordinatorSet.instance().remove(pc);
|
||||
if (pc != null && _peerCoordinatorSet != null)
|
||||
_peerCoordinatorSet.remove(pc);
|
||||
}
|
||||
|
||||
static Snark parseArguments(String[] args)
|
||||
@ -522,7 +544,8 @@ public class Snark
|
||||
String ip = null;
|
||||
String torrent = null;
|
||||
|
||||
boolean configured = I2PSnarkUtil.instance().configured();
|
||||
I2PSnarkUtil util = new I2PSnarkUtil(I2PAppContext.getGlobalContext());
|
||||
boolean configured = util.configured();
|
||||
|
||||
int i = 0;
|
||||
while (i < args.length)
|
||||
@ -572,7 +595,7 @@ public class Snark
|
||||
String proxyHost = args[i+1];
|
||||
String proxyPort = args[i+2];
|
||||
if (!configured)
|
||||
I2PSnarkUtil.instance().setProxy(proxyHost, Integer.parseInt(proxyPort));
|
||||
util.setProxy(proxyHost, Integer.parseInt(proxyPort));
|
||||
i += 3;
|
||||
}
|
||||
else if (args[i].equals("--i2cp"))
|
||||
@ -594,7 +617,7 @@ public class Snark
|
||||
}
|
||||
}
|
||||
if (!configured)
|
||||
I2PSnarkUtil.instance().setI2CPConfig(i2cpHost, Integer.parseInt(i2cpPort), opts);
|
||||
util.setI2CPConfig(i2cpHost, Integer.parseInt(i2cpPort), opts);
|
||||
i += 3 + (opts != null ? 1 : 0);
|
||||
}
|
||||
else
|
||||
@ -611,7 +634,7 @@ public class Snark
|
||||
else
|
||||
usage("Need exactly one <url>, <file> or <dir>.");
|
||||
|
||||
return new Snark(torrent, ip, user_port, slistener, clistener);
|
||||
return new Snark(util, torrent, ip, user_port, slistener, clistener);
|
||||
}
|
||||
|
||||
private static void usage(String s)
|
||||
@ -678,7 +701,7 @@ public class Snark
|
||||
*/
|
||||
public void fatal(String s, Throwable t)
|
||||
{
|
||||
I2PSnarkUtil.instance().debug(s, ERROR, t);
|
||||
_util.debug(s, ERROR, t);
|
||||
//System.err.println("snark: " + s + ((t == null) ? "" : (": " + t)));
|
||||
//if (debug >= INFO && t != null)
|
||||
// t.printStackTrace();
|
||||
@ -689,13 +712,12 @@ public class Snark
|
||||
/**
|
||||
* Show debug info if debug is true.
|
||||
*/
|
||||
public static void debug(String s, int level)
|
||||
private void debug(String s, int level)
|
||||
{
|
||||
I2PSnarkUtil.instance().debug(s, level, null);
|
||||
//if (debug >= level)
|
||||
// System.out.println(s);
|
||||
_util.debug(s, level, null);
|
||||
}
|
||||
|
||||
/** coordinatorListener */
|
||||
public void peerChange(PeerCoordinator coordinator, Peer peer)
|
||||
{
|
||||
// System.out.println(peer.toString());
|
||||
@ -742,7 +764,7 @@ public class Snark
|
||||
checking = true;
|
||||
}
|
||||
if (!checking)
|
||||
Snark.debug("Got " + (checked ? "" : "BAD ") + "piece: " + num,
|
||||
debug("Got " + (checked ? "" : "BAD ") + "piece: " + num,
|
||||
Snark.INFO);
|
||||
}
|
||||
|
||||
@ -759,7 +781,7 @@ public class Snark
|
||||
|
||||
public void storageCompleted(Storage storage)
|
||||
{
|
||||
Snark.debug("Completely received " + torrent, Snark.INFO);
|
||||
debug("Completely received " + torrent, Snark.INFO);
|
||||
//storage.close();
|
||||
//System.out.println("Completely received: " + torrent);
|
||||
if (completeListener != null)
|
||||
@ -787,41 +809,40 @@ public class Snark
|
||||
}
|
||||
|
||||
/** Maintain a configurable total uploader cap
|
||||
* coordinatorListener
|
||||
*/
|
||||
final static int MIN_TOTAL_UPLOADERS = 4;
|
||||
final static int MAX_TOTAL_UPLOADERS = 10;
|
||||
public static boolean overUploadLimit(int uploaders) {
|
||||
PeerCoordinatorSet coordinators = PeerCoordinatorSet.instance();
|
||||
if (coordinators == null || uploaders <= 0)
|
||||
public boolean overUploadLimit(int uploaders) {
|
||||
if (_peerCoordinatorSet == null || uploaders <= 0)
|
||||
return false;
|
||||
int totalUploaders = 0;
|
||||
for (Iterator iter = coordinators.iterator(); iter.hasNext(); ) {
|
||||
for (Iterator iter = _peerCoordinatorSet.iterator(); iter.hasNext(); ) {
|
||||
PeerCoordinator c = (PeerCoordinator)iter.next();
|
||||
if (!c.halted())
|
||||
totalUploaders += c.uploaders;
|
||||
}
|
||||
int limit = I2PSnarkUtil.instance().getMaxUploaders();
|
||||
// Snark.debug("Total uploaders: " + totalUploaders + " Limit: " + limit, Snark.DEBUG);
|
||||
int limit = _util.getMaxUploaders();
|
||||
// debug("Total uploaders: " + totalUploaders + " Limit: " + limit, Snark.DEBUG);
|
||||
return totalUploaders > limit;
|
||||
}
|
||||
|
||||
public static boolean overUpBWLimit() {
|
||||
PeerCoordinatorSet coordinators = PeerCoordinatorSet.instance();
|
||||
if (coordinators == null)
|
||||
public boolean overUpBWLimit() {
|
||||
if (_peerCoordinatorSet == null)
|
||||
return false;
|
||||
long total = 0;
|
||||
for (Iterator iter = coordinators.iterator(); iter.hasNext(); ) {
|
||||
for (Iterator iter = _peerCoordinatorSet.iterator(); iter.hasNext(); ) {
|
||||
PeerCoordinator c = (PeerCoordinator)iter.next();
|
||||
if (!c.halted())
|
||||
total += c.getCurrentUploadRate();
|
||||
}
|
||||
long limit = 1024l * I2PSnarkUtil.instance().getMaxUpBW();
|
||||
Snark.debug("Total up bw: " + total + " Limit: " + limit, Snark.WARNING);
|
||||
long limit = 1024l * _util.getMaxUpBW();
|
||||
debug("Total up bw: " + total + " Limit: " + limit, Snark.WARNING);
|
||||
return total > limit;
|
||||
}
|
||||
|
||||
public static boolean overUpBWLimit(long total) {
|
||||
long limit = 1024l * I2PSnarkUtil.instance().getMaxUpBW();
|
||||
public boolean overUpBWLimit(long total) {
|
||||
long limit = 1024l * _util.getMaxUpBW();
|
||||
return total > limit;
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,9 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
private I2PAppContext _context;
|
||||
private Log _log;
|
||||
private List _messages;
|
||||
private I2PSnarkUtil _util;
|
||||
private PeerCoordinatorSet _peerCoordinatorSet;
|
||||
private ConnectionAcceptor _connectionAcceptor;
|
||||
|
||||
public static final String PROP_I2CP_HOST = "i2psnark.i2cpHost";
|
||||
public static final String PROP_I2CP_PORT = "i2psnark.i2cpPort";
|
||||
@ -63,6 +66,9 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
_context = I2PAppContext.getGlobalContext();
|
||||
_log = _context.logManager().getLog(SnarkManager.class);
|
||||
_messages = new ArrayList(16);
|
||||
_util = new I2PSnarkUtil(_context);
|
||||
_peerCoordinatorSet = new PeerCoordinatorSet();
|
||||
_connectionAcceptor = new ConnectionAcceptor(_util);
|
||||
loadConfig("i2psnark.config");
|
||||
int minutes = getStartupDelayMinutes();
|
||||
_messages.add("Adding torrents in " + minutes + (minutes == 1 ? " minute" : " minutes"));
|
||||
@ -73,6 +79,9 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
((RouterContext)_context).router().addShutdownTask(new SnarkManagerShutdown());
|
||||
}
|
||||
|
||||
/** hook to I2PSnarkUtil for the servlet */
|
||||
public I2PSnarkUtil util() { return _util; }
|
||||
|
||||
private static final int MAX_MESSAGES = 5;
|
||||
public void addMessage(String message) {
|
||||
synchronized (_messages) {
|
||||
@ -162,16 +171,16 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
}
|
||||
}
|
||||
if (i2cpHost != null) {
|
||||
I2PSnarkUtil.instance().setI2CPConfig(i2cpHost, i2cpPort, i2cpOpts);
|
||||
_util.setI2CPConfig(i2cpHost, i2cpPort, i2cpOpts);
|
||||
_log.debug("Configuring with I2CP options " + i2cpOpts);
|
||||
}
|
||||
//I2PSnarkUtil.instance().setI2CPConfig("66.111.51.110", 7654, new Properties());
|
||||
String eepHost = _config.getProperty(PROP_EEP_HOST);
|
||||
int eepPort = getInt(PROP_EEP_PORT, 4444);
|
||||
if (eepHost != null)
|
||||
I2PSnarkUtil.instance().setProxy(eepHost, eepPort);
|
||||
I2PSnarkUtil.instance().setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS));
|
||||
I2PSnarkUtil.instance().setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
|
||||
_util.setProxy(eepHost, eepPort);
|
||||
_util.setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS));
|
||||
_util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
|
||||
getDataDir().mkdirs();
|
||||
}
|
||||
|
||||
@ -191,12 +200,12 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
String upLimit, String upBW, boolean useOpenTrackers, String openTrackers) {
|
||||
boolean changed = false;
|
||||
if (eepHost != null) {
|
||||
int port = I2PSnarkUtil.instance().getEepProxyPort();
|
||||
int port = _util.getEepProxyPort();
|
||||
try { port = Integer.parseInt(eepPort); } catch (NumberFormatException nfe) {}
|
||||
String host = I2PSnarkUtil.instance().getEepProxyHost();
|
||||
String host = _util.getEepProxyHost();
|
||||
if ( (eepHost.trim().length() > 0) && (port > 0) &&
|
||||
((!host.equals(eepHost) || (port != I2PSnarkUtil.instance().getEepProxyPort()) )) ) {
|
||||
I2PSnarkUtil.instance().setProxy(eepHost, port);
|
||||
((!host.equals(eepHost) || (port != _util.getEepProxyPort()) )) ) {
|
||||
_util.setProxy(eepHost, port);
|
||||
changed = true;
|
||||
_config.setProperty(PROP_EEP_HOST, eepHost);
|
||||
_config.setProperty(PROP_EEP_PORT, eepPort+"");
|
||||
@ -204,11 +213,11 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
}
|
||||
}
|
||||
if (upLimit != null) {
|
||||
int limit = I2PSnarkUtil.instance().getMaxUploaders();
|
||||
int limit = _util.getMaxUploaders();
|
||||
try { limit = Integer.parseInt(upLimit); } catch (NumberFormatException nfe) {}
|
||||
if ( limit != I2PSnarkUtil.instance().getMaxUploaders()) {
|
||||
if ( limit != _util.getMaxUploaders()) {
|
||||
if ( limit >= Snark.MIN_TOTAL_UPLOADERS ) {
|
||||
I2PSnarkUtil.instance().setMaxUploaders(limit);
|
||||
_util.setMaxUploaders(limit);
|
||||
changed = true;
|
||||
_config.setProperty(PROP_UPLOADERS_TOTAL, "" + limit);
|
||||
addMessage("Total uploaders limit changed to " + limit);
|
||||
@ -218,11 +227,11 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
}
|
||||
}
|
||||
if (upBW != null) {
|
||||
int limit = I2PSnarkUtil.instance().getMaxUpBW();
|
||||
int limit = _util.getMaxUpBW();
|
||||
try { limit = Integer.parseInt(upBW); } catch (NumberFormatException nfe) {}
|
||||
if ( limit != I2PSnarkUtil.instance().getMaxUpBW()) {
|
||||
if ( limit != _util.getMaxUpBW()) {
|
||||
if ( limit >= MIN_UP_BW ) {
|
||||
I2PSnarkUtil.instance().setMaxUpBW(limit);
|
||||
_util.setMaxUpBW(limit);
|
||||
changed = true;
|
||||
_config.setProperty(PROP_UPBW_MAX, "" + limit);
|
||||
addMessage("Up BW limit changed to " + limit + "KBps");
|
||||
@ -232,8 +241,8 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
}
|
||||
}
|
||||
if (i2cpHost != null) {
|
||||
int oldI2CPPort = I2PSnarkUtil.instance().getI2CPPort();
|
||||
String oldI2CPHost = I2PSnarkUtil.instance().getI2CPHost();
|
||||
int oldI2CPPort = _util.getI2CPPort();
|
||||
String oldI2CPHost = _util.getI2CPHost();
|
||||
int port = oldI2CPPort;
|
||||
try { port = Integer.parseInt(i2cpPort); } catch (NumberFormatException nfe) {}
|
||||
String host = oldI2CPHost;
|
||||
@ -259,7 +268,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
|
||||
if ( (i2cpHost.trim().length() > 0) && (port > 0) &&
|
||||
((!host.equals(i2cpHost) ||
|
||||
(port != I2PSnarkUtil.instance().getI2CPPort()) ||
|
||||
(port != _util.getI2CPPort()) ||
|
||||
(!oldOpts.equals(opts)))) ) {
|
||||
boolean snarksActive = false;
|
||||
Set names = listTorrentFiles();
|
||||
@ -275,19 +284,19 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
_log.debug("i2cp host [" + i2cpHost + "] i2cp port " + port + " opts [" + opts
|
||||
+ "] oldOpts [" + oldOpts + "]");
|
||||
} else {
|
||||
if (I2PSnarkUtil.instance().connected()) {
|
||||
I2PSnarkUtil.instance().disconnect();
|
||||
if (_util.connected()) {
|
||||
_util.disconnect();
|
||||
addMessage("Disconnecting old I2CP destination");
|
||||
}
|
||||
Properties p = new Properties();
|
||||
p.putAll(opts);
|
||||
addMessage("I2CP settings changed to " + i2cpHost + ":" + port + " (" + i2cpOpts.trim() + ")");
|
||||
I2PSnarkUtil.instance().setI2CPConfig(i2cpHost, port, p);
|
||||
boolean ok = I2PSnarkUtil.instance().connect();
|
||||
_util.setI2CPConfig(i2cpHost, port, p);
|
||||
boolean ok = _util.connect();
|
||||
if (!ok) {
|
||||
addMessage("Unable to connect with the new settings, reverting to the old I2CP settings");
|
||||
I2PSnarkUtil.instance().setI2CPConfig(oldI2CPHost, oldI2CPPort, oldOpts);
|
||||
ok = I2PSnarkUtil.instance().connect();
|
||||
_util.setI2CPConfig(oldI2CPHost, oldI2CPPort, oldOpts);
|
||||
ok = _util.connect();
|
||||
if (!ok)
|
||||
addMessage("Unable to reconnect with the old settings!");
|
||||
} else {
|
||||
@ -315,13 +324,13 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
addMessage("Adjusted autostart to " + autoStart);
|
||||
changed = true;
|
||||
}
|
||||
if (I2PSnarkUtil.instance().shouldUseOpenTrackers() != useOpenTrackers) {
|
||||
if (_util.shouldUseOpenTrackers() != useOpenTrackers) {
|
||||
_config.setProperty(I2PSnarkUtil.PROP_USE_OPENTRACKERS, useOpenTrackers + "");
|
||||
addMessage((useOpenTrackers ? "En" : "Dis") + "abled open trackers - torrent restart required to take effect");
|
||||
changed = true;
|
||||
}
|
||||
if (openTrackers != null) {
|
||||
if (openTrackers.trim().length() > 0 && !openTrackers.trim().equals(I2PSnarkUtil.instance().getOpenTrackerString())) {
|
||||
if (openTrackers.trim().length() > 0 && !openTrackers.trim().equals(_util.getOpenTrackerString())) {
|
||||
_config.setProperty(I2PSnarkUtil.PROP_OPENTRACKERS, openTrackers.trim());
|
||||
addMessage("Open Tracker list changed - torrent restart required to take effect");
|
||||
changed = true;
|
||||
@ -357,9 +366,9 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
public Snark getTorrent(String filename) { synchronized (_snarks) { return (Snark)_snarks.get(filename); } }
|
||||
public void addTorrent(String filename) { addTorrent(filename, false); }
|
||||
public void addTorrent(String filename, boolean dontAutoStart) {
|
||||
if ((!dontAutoStart) && !I2PSnarkUtil.instance().connected()) {
|
||||
if ((!dontAutoStart) && !_util.connected()) {
|
||||
addMessage("Connecting to I2P");
|
||||
boolean ok = I2PSnarkUtil.instance().connect();
|
||||
boolean ok = _util.connect();
|
||||
if (!ok) {
|
||||
addMessage("Error connecting to I2P - check your I2CP settings");
|
||||
return;
|
||||
@ -400,7 +409,9 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
addMessage(rejectMessage);
|
||||
return;
|
||||
} else {
|
||||
torrent = new Snark(filename, null, -1, null, null, this, false, dataDir.getPath());
|
||||
torrent = new Snark(_util, filename, null, -1, null, null, this,
|
||||
_peerCoordinatorSet, _connectionAcceptor,
|
||||
false, dataDir.getPath());
|
||||
torrent.completeListener = this;
|
||||
synchronized (_snarks) {
|
||||
_snarks.put(filename, torrent);
|
||||
@ -569,7 +580,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
if (remaining == 0) {
|
||||
// should we disconnect/reconnect here (taking care to deal with the other thread's
|
||||
// I2PServerSocket.accept() call properly?)
|
||||
////I2PSnarkUtil.instance().
|
||||
////_util.
|
||||
}
|
||||
if (!wasStopped)
|
||||
addMessage("Torrent stopped: '" + sfile.getName() + "'");
|
||||
@ -645,7 +656,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
if (existingNames.contains(foundNames.get(i))) {
|
||||
// already known. noop
|
||||
} else {
|
||||
if (shouldAutoStart() && !I2PSnarkUtil.instance().connect())
|
||||
if (shouldAutoStart() && !_util.connect())
|
||||
addMessage("Unable to connect to I2P");
|
||||
addTorrent((String)foundNames.get(i), !shouldAutoStart());
|
||||
}
|
||||
|
@ -51,21 +51,21 @@ public class SnarkShutdown extends I2PThread
|
||||
|
||||
public void run()
|
||||
{
|
||||
Snark.debug("Shutting down...", Snark.NOTICE);
|
||||
//Snark.debug("Shutting down...", Snark.NOTICE);
|
||||
|
||||
Snark.debug("Halting ConnectionAcceptor...", Snark.INFO);
|
||||
//Snark.debug("Halting ConnectionAcceptor...", Snark.INFO);
|
||||
if (acceptor != null)
|
||||
acceptor.halt();
|
||||
|
||||
Snark.debug("Halting TrackerClient...", Snark.INFO);
|
||||
//Snark.debug("Halting TrackerClient...", Snark.INFO);
|
||||
if (trackerclient != null)
|
||||
trackerclient.halt();
|
||||
|
||||
Snark.debug("Halting PeerCoordinator...", Snark.INFO);
|
||||
//Snark.debug("Halting PeerCoordinator...", Snark.INFO);
|
||||
if (coordinator != null)
|
||||
coordinator.halt();
|
||||
|
||||
Snark.debug("Closing Storage...", Snark.INFO);
|
||||
//Snark.debug("Closing Storage...", Snark.INFO);
|
||||
if (storage != null)
|
||||
{
|
||||
try
|
||||
@ -74,7 +74,7 @@ public class SnarkShutdown extends I2PThread
|
||||
}
|
||||
catch(IOException ioe)
|
||||
{
|
||||
I2PSnarkUtil.instance().debug("Couldn't properly close storage", Snark.ERROR, ioe);
|
||||
//I2PSnarkUtil.instance().debug("Couldn't properly close storage", Snark.ERROR, ioe);
|
||||
throw new RuntimeException("b0rking");
|
||||
}
|
||||
}
|
||||
@ -82,7 +82,7 @@ public class SnarkShutdown extends I2PThread
|
||||
// XXX - Should actually wait till done...
|
||||
try
|
||||
{
|
||||
Snark.debug("Waiting 5 seconds...", Snark.INFO);
|
||||
//Snark.debug("Waiting 5 seconds...", Snark.INFO);
|
||||
Thread.sleep(5*1000);
|
||||
}
|
||||
catch (InterruptedException ie) { /* ignored */ }
|
||||
|
@ -44,6 +44,7 @@ public class Storage
|
||||
private File[] RAFfile; // File to make it easier to reopen
|
||||
|
||||
private final StorageListener listener;
|
||||
private I2PSnarkUtil _util;
|
||||
|
||||
private BitField bitfield; // BitField to represent the pieces
|
||||
private int needed; // Number of pieces needed
|
||||
@ -66,9 +67,10 @@ public class Storage
|
||||
*
|
||||
* @exception IOException when creating and/or checking files fails.
|
||||
*/
|
||||
public Storage(MetaInfo metainfo, StorageListener listener)
|
||||
public Storage(I2PSnarkUtil util, MetaInfo metainfo, StorageListener listener)
|
||||
throws IOException
|
||||
{
|
||||
_util = util;
|
||||
this.metainfo = metainfo;
|
||||
this.listener = listener;
|
||||
needed = metainfo.getPieces();
|
||||
@ -81,9 +83,10 @@ public class Storage
|
||||
* with an appropriate MetaInfo file as can be announced on the
|
||||
* given announce String location.
|
||||
*/
|
||||
public Storage(File baseFile, String announce, StorageListener listener)
|
||||
public Storage(I2PSnarkUtil util, File baseFile, String announce, StorageListener listener)
|
||||
throws IOException
|
||||
{
|
||||
_util = util;
|
||||
this.listener = listener;
|
||||
// Create names, rafs and lengths arrays.
|
||||
getFiles(baseFile);
|
||||
@ -236,7 +239,7 @@ public class Storage
|
||||
}
|
||||
}
|
||||
|
||||
private static void addFiles(List l, File f)
|
||||
private void addFiles(List l, File f)
|
||||
{
|
||||
if (!f.isDirectory())
|
||||
l.add(f);
|
||||
@ -245,7 +248,7 @@ public class Storage
|
||||
File[] files = f.listFiles();
|
||||
if (files == null)
|
||||
{
|
||||
Snark.debug("WARNING: Skipping '" + f
|
||||
_util.debug("WARNING: Skipping '" + f
|
||||
+ "' not a normal file.", Snark.WARNING);
|
||||
return;
|
||||
}
|
||||
@ -305,7 +308,7 @@ public class Storage
|
||||
if (files == null)
|
||||
{
|
||||
// Create base as file.
|
||||
Snark.debug("Creating/Checking file: " + base, Snark.NOTICE);
|
||||
_util.debug("Creating/Checking file: " + base, Snark.NOTICE);
|
||||
if (!base.createNewFile() && !base.exists())
|
||||
throw new IOException("Could not create file " + base);
|
||||
|
||||
@ -328,7 +331,7 @@ public class Storage
|
||||
else
|
||||
{
|
||||
// Create base as dir.
|
||||
Snark.debug("Creating/Checking directory: " + base, Snark.NOTICE);
|
||||
_util.debug("Creating/Checking directory: " + base, Snark.NOTICE);
|
||||
if (!base.mkdir() && !base.isDirectory())
|
||||
throw new IOException("Could not create directory " + base);
|
||||
|
||||
@ -366,16 +369,16 @@ public class Storage
|
||||
bitfield = savedBitField;
|
||||
needed = metainfo.getPieces() - bitfield.count();
|
||||
_probablyComplete = complete();
|
||||
Snark.debug("Found saved state and files unchanged, skipping check", Snark.NOTICE);
|
||||
_util.debug("Found saved state and files unchanged, skipping check", Snark.NOTICE);
|
||||
} else {
|
||||
// the following sets the needed variable
|
||||
changed = true;
|
||||
checkCreateFiles();
|
||||
}
|
||||
if (complete())
|
||||
Snark.debug("Torrent is complete", Snark.NOTICE);
|
||||
_util.debug("Torrent is complete", Snark.NOTICE);
|
||||
else
|
||||
Snark.debug("Still need " + needed + " out of " + metainfo.getPieces() + " pieces", Snark.NOTICE);
|
||||
_util.debug("Still need " + needed + " out of " + metainfo.getPieces() + " pieces", Snark.NOTICE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -390,14 +393,14 @@ public class Storage
|
||||
if (files == null)
|
||||
{
|
||||
// Reopen base as file.
|
||||
Snark.debug("Reopening file: " + base, Snark.NOTICE);
|
||||
_util.debug("Reopening file: " + base, Snark.NOTICE);
|
||||
if (!base.exists())
|
||||
throw new IOException("Could not reopen file " + base);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reopen base as dir.
|
||||
Snark.debug("Reopening directory: " + base, Snark.NOTICE);
|
||||
_util.debug("Reopening directory: " + base, Snark.NOTICE);
|
||||
if (!base.isDirectory())
|
||||
throw new IOException("Could not reopen directory " + base);
|
||||
|
||||
@ -487,7 +490,7 @@ public class Storage
|
||||
allocateFile(i);
|
||||
}
|
||||
} else {
|
||||
Snark.debug("File '" + names[i] + "' exists, but has wrong length - repairing corruption", Snark.ERROR);
|
||||
_util.debug("File '" + names[i] + "' exists, but has wrong length - repairing corruption", Snark.ERROR);
|
||||
changed = true;
|
||||
_probablyComplete = false; // to force RW
|
||||
synchronized(RAFlock[i]) {
|
||||
@ -574,7 +577,7 @@ public class Storage
|
||||
closeRAF(i);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
I2PSnarkUtil.instance().debug("Error closing " + RAFfile[i], Snark.ERROR, ioe);
|
||||
_util.debug("Error closing " + RAFfile[i], Snark.ERROR, ioe);
|
||||
// gobble gobble
|
||||
}
|
||||
}
|
||||
@ -595,7 +598,7 @@ public class Storage
|
||||
try {
|
||||
bs = new byte[len];
|
||||
} catch (OutOfMemoryError oom) {
|
||||
I2PSnarkUtil.instance().debug("Out of memory, can't honor request for piece " + piece, Snark.WARNING, oom);
|
||||
_util.debug("Out of memory, can't honor request for piece " + piece, Snark.WARNING, oom);
|
||||
return null;
|
||||
}
|
||||
getUncheckedPiece(piece, bs, off, len);
|
||||
@ -691,7 +694,7 @@ public class Storage
|
||||
if (needed > 0) {
|
||||
if (listener != null)
|
||||
listener.setWantedPieces(this);
|
||||
Snark.debug("WARNING: Not really done, missing " + needed
|
||||
_util.debug("WARNING: Not really done, missing " + needed
|
||||
+ " pieces", Snark.WARNING);
|
||||
} else {
|
||||
if (listener != null)
|
||||
|
@ -57,6 +57,7 @@ public class TrackerClient extends I2PThread
|
||||
private final static int MAX_CONSEC_FAILS = 5; // slow down after this
|
||||
private final static int LONG_SLEEP = 30*60*1000; // sleep a while after lots of fails
|
||||
|
||||
private I2PSnarkUtil _util;
|
||||
private final MetaInfo meta;
|
||||
private final PeerCoordinator coordinator;
|
||||
private final int port;
|
||||
@ -66,10 +67,11 @@ public class TrackerClient extends I2PThread
|
||||
|
||||
private List trackers;
|
||||
|
||||
public TrackerClient(MetaInfo meta, PeerCoordinator coordinator)
|
||||
public TrackerClient(I2PSnarkUtil util, MetaInfo meta, PeerCoordinator coordinator)
|
||||
{
|
||||
// Set unique name.
|
||||
super("TrackerClient-" + urlencode(coordinator.getID()));
|
||||
_util = util;
|
||||
this.meta = meta;
|
||||
this.coordinator = coordinator;
|
||||
|
||||
@ -98,13 +100,13 @@ public class TrackerClient extends I2PThread
|
||||
}
|
||||
|
||||
private boolean verifyConnected() {
|
||||
while (!stop && !I2PSnarkUtil.instance().connected()) {
|
||||
boolean ok = I2PSnarkUtil.instance().connect();
|
||||
while (!stop && !_util.connected()) {
|
||||
boolean ok = _util.connect();
|
||||
if (!ok) {
|
||||
try { Thread.sleep(30*1000); } catch (InterruptedException ie) {}
|
||||
}
|
||||
}
|
||||
return !stop && I2PSnarkUtil.instance().connected();
|
||||
return !stop && _util.connected();
|
||||
}
|
||||
|
||||
public void run()
|
||||
@ -121,7 +123,7 @@ public class TrackerClient extends I2PThread
|
||||
// the primary tracker, that we don't add it twice.
|
||||
trackers = new ArrayList(2);
|
||||
trackers.add(new Tracker(meta.getAnnounce(), true));
|
||||
List tlist = I2PSnarkUtil.instance().getOpenTrackers();
|
||||
List tlist = _util.getOpenTrackers();
|
||||
if (tlist != null) {
|
||||
for (int i = 0; i < tlist.size(); i++) {
|
||||
String url = (String)tlist.get(i);
|
||||
@ -136,7 +138,7 @@ public class TrackerClient extends I2PThread
|
||||
}
|
||||
if (meta.getAnnounce().startsWith(url.substring(0, slash)))
|
||||
continue;
|
||||
String dest = I2PSnarkUtil.instance().lookup(url.substring(7, slash));
|
||||
String dest = _util.lookup(url.substring(7, slash));
|
||||
if (dest == null) {
|
||||
_log.error("Announce host unknown: [" + url + "]");
|
||||
continue;
|
||||
@ -264,7 +266,7 @@ public class TrackerClient extends I2PThread
|
||||
catch (IOException ioe)
|
||||
{
|
||||
// Probably not fatal (if it doesn't last to long...)
|
||||
Snark.debug
|
||||
_util.debug
|
||||
("WARNING: Could not contact tracker at '"
|
||||
+ tr.announce + "': " + ioe, Snark.WARNING);
|
||||
tr.trackerProblems = ioe.getMessage();
|
||||
@ -295,12 +297,12 @@ public class TrackerClient extends I2PThread
|
||||
// we could try and total the unique peers but that's too hard for now
|
||||
coordinator.trackerSeenPeers = maxSeenPeers;
|
||||
if (!started)
|
||||
Snark.debug(" Retrying in one minute...", Snark.DEBUG);
|
||||
_util.debug(" Retrying in one minute...", Snark.DEBUG);
|
||||
} // *** end of while loop
|
||||
} // try
|
||||
catch (Throwable t)
|
||||
{
|
||||
I2PSnarkUtil.instance().debug("TrackerClient: " + t, Snark.ERROR, t);
|
||||
_util.debug("TrackerClient: " + t, Snark.ERROR, t);
|
||||
if (t instanceof OutOfMemoryError)
|
||||
throw (OutOfMemoryError)t;
|
||||
}
|
||||
@ -332,15 +334,15 @@ public class TrackerClient extends I2PThread
|
||||
+ "?info_hash=" + infoHash
|
||||
+ "&peer_id=" + peerID
|
||||
+ "&port=" + port
|
||||
+ "&ip=" + I2PSnarkUtil.instance().getOurIPString() + ".i2p"
|
||||
+ "&ip=" + _util.getOurIPString() + ".i2p"
|
||||
+ "&uploaded=" + uploaded
|
||||
+ "&downloaded=" + downloaded
|
||||
+ "&left=" + left
|
||||
+ ((event != NO_EVENT) ? ("&event=" + event) : "");
|
||||
Snark.debug("Sending TrackerClient request: " + s, Snark.INFO);
|
||||
_util.debug("Sending TrackerClient request: " + s, Snark.INFO);
|
||||
|
||||
tr.lastRequestTime = System.currentTimeMillis();
|
||||
File fetched = I2PSnarkUtil.instance().get(s);
|
||||
File fetched = _util.get(s);
|
||||
if (fetched == null) {
|
||||
throw new IOException("Error fetching " + s);
|
||||
}
|
||||
@ -352,7 +354,7 @@ public class TrackerClient extends I2PThread
|
||||
|
||||
TrackerInfo info = new TrackerInfo(in, coordinator.getID(),
|
||||
coordinator.getMetaInfo());
|
||||
Snark.debug("TrackerClient response: " + info, Snark.INFO);
|
||||
_util.debug("TrackerClient response: " + info, Snark.INFO);
|
||||
|
||||
String failure = info.getFailureReason();
|
||||
if (failure != null)
|
||||
|
@ -101,7 +101,7 @@ public class TrackerInfo
|
||||
peerID = new PeerID(((BEValue)it.next()).getMap());
|
||||
} catch (InvalidBEncodingException ibe) {
|
||||
// don't let one bad entry spoil the whole list
|
||||
Snark.debug("Discarding peer from list: " + ibe, Snark.ERROR);
|
||||
//Snark.debug("Discarding peer from list: " + ibe, Snark.ERROR);
|
||||
continue;
|
||||
}
|
||||
peers.add(new Peer(peerID, my_id, metainfo));
|
||||
|
@ -116,7 +116,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
List snarks = getSortedSnarks(req);
|
||||
String uri = req.getRequestURI();
|
||||
out.write(TABLE_HEADER);
|
||||
if (I2PSnarkUtil.instance().connected() && snarks.size() > 0) {
|
||||
if (_manager.util().connected() && snarks.size() > 0) {
|
||||
if (peerParam != null)
|
||||
out.write("(<a href=\"" + req.getRequestURI() + "\">Hide Peers</a>)<br />\n");
|
||||
else
|
||||
@ -124,7 +124,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
}
|
||||
out.write(TABLE_HEADER2);
|
||||
out.write("<th align=\"left\" valign=\"top\">");
|
||||
if (I2PSnarkUtil.instance().connected())
|
||||
if (_manager.util().connected())
|
||||
out.write("<a href=\"" + uri + "?action=StopAll&nonce=" + _nonce +
|
||||
"\" title=\"Stop all torrents and the i2p tunnel\">Stop All</a>");
|
||||
else if (snarks.size() > 0)
|
||||
@ -330,7 +330,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
_manager.addMessage("Error creating torrent - you must select a tracker");
|
||||
else if (baseFile.exists()) {
|
||||
try {
|
||||
Storage s = new Storage(baseFile, announceURL, null);
|
||||
Storage s = new Storage(_manager.util(), baseFile, announceURL, null);
|
||||
s.create();
|
||||
s.close(); // close the files... maybe need a way to pass this Storage to addTorrent rather than starting over
|
||||
MetaInfo info = s.getMetaInfo();
|
||||
@ -361,8 +361,8 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
if (!snark.stopped)
|
||||
_manager.stopTorrent(snark.torrent, false);
|
||||
}
|
||||
if (I2PSnarkUtil.instance().connected()) {
|
||||
I2PSnarkUtil.instance().disconnect();
|
||||
if (_manager.util().connected()) {
|
||||
_manager.util().disconnect();
|
||||
_manager.addMessage("I2P tunnel closed");
|
||||
}
|
||||
} else if ("StartAll".equals(action)) {
|
||||
@ -690,8 +690,8 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
String uri = req.getRequestURI();
|
||||
String dataDir = _manager.getDataDir().getAbsolutePath();
|
||||
boolean autoStart = _manager.shouldAutoStart();
|
||||
boolean useOpenTrackers = I2PSnarkUtil.instance().shouldUseOpenTrackers();
|
||||
String openTrackers = I2PSnarkUtil.instance().getOpenTrackerString();
|
||||
boolean useOpenTrackers = _manager.util().shouldUseOpenTrackers();
|
||||
String openTrackers = _manager.util().getOpenTrackerString();
|
||||
//int seedPct = 0;
|
||||
|
||||
out.write("<form action=\"" + uri + "\" method=\"POST\">\n");
|
||||
@ -723,9 +723,9 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
out.write("</select><br />\n");
|
||||
*/
|
||||
out.write("Total uploader limit: <input type=\"text\" name=\"upLimit\" value=\""
|
||||
+ I2PSnarkUtil.instance().getMaxUploaders() + "\" size=\"3\" maxlength=\"3\" /> peers<br />\n");
|
||||
+ _manager.util().getMaxUploaders() + "\" size=\"3\" maxlength=\"3\" /> peers<br />\n");
|
||||
out.write("Up bandwidth limit: <input type=\"text\" name=\"upBW\" value=\""
|
||||
+ I2PSnarkUtil.instance().getMaxUpBW() + "\" size=\"3\" maxlength=\"3\" /> KBps <i>(Router Up BW / 2 recommended)</i><br />\n");
|
||||
+ _manager.util().getMaxUpBW() + "\" size=\"3\" maxlength=\"3\" /> KBps <i>(Router Up BW / 2 recommended)</i><br />\n");
|
||||
|
||||
out.write("Use open trackers also: <input type=\"checkbox\" name=\"useOpenTrackers\" value=\"true\" "
|
||||
+ (useOpenTrackers ? "checked " : "")
|
||||
@ -735,15 +735,15 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
|
||||
//out.write("<hr />\n");
|
||||
out.write("EepProxy host: <input type=\"text\" name=\"eepHost\" value=\""
|
||||
+ I2PSnarkUtil.instance().getEepProxyHost() + "\" size=\"15\" /> ");
|
||||
+ _manager.util().getEepProxyHost() + "\" size=\"15\" /> ");
|
||||
out.write("port: <input type=\"text\" name=\"eepPort\" value=\""
|
||||
+ I2PSnarkUtil.instance().getEepProxyPort() + "\" size=\"5\" maxlength=\"5\" /><br />\n");
|
||||
+ _manager.util().getEepProxyPort() + "\" size=\"5\" maxlength=\"5\" /><br />\n");
|
||||
out.write("I2CP host: <input type=\"text\" name=\"i2cpHost\" value=\""
|
||||
+ I2PSnarkUtil.instance().getI2CPHost() + "\" size=\"15\" /> ");
|
||||
+ _manager.util().getI2CPHost() + "\" size=\"15\" /> ");
|
||||
out.write("port: <input type=\"text\" name=\"i2cpPort\" value=\"" +
|
||||
+ I2PSnarkUtil.instance().getI2CPPort() + "\" size=\"5\" maxlength=\"5\" /> <br />\n");
|
||||
+ _manager.util().getI2CPPort() + "\" size=\"5\" maxlength=\"5\" /> <br />\n");
|
||||
StringBuffer opts = new StringBuffer(64);
|
||||
Map options = new TreeMap(I2PSnarkUtil.instance().getI2CPOptions());
|
||||
Map options = new TreeMap(_manager.util().getI2CPOptions());
|
||||
for (Iterator iter = options.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry entry = (Map.Entry)iter.next();
|
||||
String key = (String)entry.getKey();
|
||||
@ -877,7 +877,7 @@ class FetchAndAdd implements Runnable {
|
||||
public void run() {
|
||||
_url = _url.trim();
|
||||
// 3 retries
|
||||
File file = I2PSnarkUtil.instance().get(_url, false, 3);
|
||||
File file = _manager.util().get(_url, false, 3);
|
||||
try {
|
||||
if ( (file != null) && (file.exists()) && (file.length() > 0) ) {
|
||||
_manager.addMessage("Torrent fetched from " + _url);
|
||||
|
Reference in New Issue
Block a user