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:
zzz
2008-11-16 17:11:53 +00:00
parent fa23a7b066
commit 23699e46e5
15 changed files with 244 additions and 172 deletions

View File

@ -36,17 +36,16 @@ import net.i2p.util.Log;
*/ */
public class ConnectionAcceptor implements Runnable 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 Log _log = new Log(ConnectionAcceptor.class);
private I2PServerSocket serverSocket; private I2PServerSocket serverSocket;
private PeerAcceptor peeracceptor; private PeerAcceptor peeracceptor;
private Thread thread; private Thread thread;
private I2PSnarkUtil _util;
private boolean stop; private boolean stop;
private boolean socketChanged; private boolean socketChanged;
private ConnectionAcceptor() {} public ConnectionAcceptor(I2PSnarkUtil util) { _util = util; }
public synchronized void startAccepting(PeerCoordinatorSet set, I2PServerSocket socket) { public synchronized void startAccepting(PeerCoordinatorSet set, I2PServerSocket socket) {
if (serverSocket != 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) PeerAcceptor peeracceptor)
{ {
this.serverSocket = serverSocket; this.serverSocket = serverSocket;
this.peeracceptor = peeracceptor; this.peeracceptor = peeracceptor;
_util = util;
socketChanged = false; socketChanged = false;
stop = false; stop = false;
@ -78,7 +78,7 @@ public class ConnectionAcceptor implements Runnable
public void halt() public void halt()
{ {
if (true) throw new RuntimeException("wtf"); if (stop) return;
stop = true; stop = true;
I2PServerSocket ss = serverSocket; I2PServerSocket ss = serverSocket;
@ -95,7 +95,7 @@ public class ConnectionAcceptor implements Runnable
} }
public void restart() { public void restart() {
serverSocket = I2PSnarkUtil.instance().getServerSocket(); serverSocket = _util.getServerSocket();
socketChanged = true; socketChanged = true;
Thread t = thread; Thread t = thread;
if (t != null) if (t != null)
@ -116,7 +116,7 @@ public class ConnectionAcceptor implements Runnable
socketChanged = false; socketChanged = false;
} }
while ( (serverSocket == null) && (!stop)) { while ( (serverSocket == null) && (!stop)) {
serverSocket = I2PSnarkUtil.instance().getServerSocket(); serverSocket = _util.getServerSocket();
if (serverSocket == null) if (serverSocket == null)
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {} try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
} }
@ -129,7 +129,7 @@ public class ConnectionAcceptor implements Runnable
if (socketChanged) { if (socketChanged) {
continue; continue;
} else { } else {
I2PServerSocket ss = I2PSnarkUtil.instance().getServerSocket(); I2PServerSocket ss = _util.getServerSocket();
if (ss != serverSocket) { if (ss != serverSocket) {
serverSocket = ss; serverSocket = ss;
socketChanged = true; socketChanged = true;
@ -143,13 +143,13 @@ public class ConnectionAcceptor implements Runnable
catch (I2PException ioe) catch (I2PException ioe)
{ {
if (!socketChanged) { if (!socketChanged) {
Snark.debug("Error while accepting: " + ioe, Snark.ERROR); _util.debug("Error while accepting: " + ioe, Snark.ERROR);
stop = true; stop = true;
} }
} }
catch (IOException ioe) catch (IOException ioe)
{ {
Snark.debug("Error while accepting: " + ioe, Snark.ERROR); _util.debug("Error while accepting: " + ioe, Snark.ERROR);
stop = true; stop = true;
} }
} }
@ -161,7 +161,6 @@ public class ConnectionAcceptor implements Runnable
} }
catch (I2PException ignored) { } catch (I2PException ignored) { }
throw new RuntimeException("wtf");
} }
private class Handler implements Runnable { private class Handler implements Runnable {

View File

@ -30,4 +30,8 @@ public interface CoordinatorListener
* Called when the PeerCoordinator notices a change in the state of a peer. * Called when the PeerCoordinator notices a change in the state of a peer.
*/ */
void peerChange(PeerCoordinator coordinator, Peer peer); void peerChange(PeerCoordinator coordinator, Peer peer);
public boolean overUploadLimit(int uploaders);
public boolean overUpBWLimit();
public boolean overUpBWLimit(long total);
} }

View File

@ -28,12 +28,13 @@ import net.i2p.util.SimpleTimer;
/** /**
* I2P specific helpers for I2PSnark * 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 { public class I2PSnarkUtil {
private I2PAppContext _context; private I2PAppContext _context;
private Log _log; private Log _log;
private static I2PSnarkUtil _instance = new I2PSnarkUtil();
public static I2PSnarkUtil instance() { return _instance; }
private boolean _shouldProxy; private boolean _shouldProxy;
private String _proxyHost; private String _proxyHost;
@ -53,8 +54,8 @@ public class I2PSnarkUtil {
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
private I2PSnarkUtil() { public I2PSnarkUtil(I2PAppContext ctx) {
_context = I2PAppContext.getGlobalContext(); _context = ctx;
_log = _context.logManager().getLog(Snark.class); _log = _context.logManager().getLog(Snark.class);
_opts = new HashMap(); _opts = new HashMap();
setProxy("127.0.0.1", 4444); setProxy("127.0.0.1", 4444);
@ -233,6 +234,28 @@ public class I2PSnarkUtil {
} }
return "unknown"; 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) { Destination getDestination(String ip) {
if (ip == null) return null; if (ip == null) return null;
if (ip.endsWith(".i2p")) { if (ip.endsWith(".i2p")) {
@ -308,6 +331,9 @@ public class I2PSnarkUtil {
} }
/** hook between snark's logger and an i2p log */ /** 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) { void debug(String msg, int snarkDebugLevel, Throwable t) {
if (t instanceof OutOfMemoryError) { if (t instanceof OutOfMemoryError) {
try { Thread.sleep(100); } catch (InterruptedException ie) {} try { Thread.sleep(100); } catch (InterruptedException ie) {}

View File

@ -173,7 +173,7 @@ public class Peer implements Comparable
* If the given BitField is non-null it is send to the peer as first * If the given BitField is non-null it is send to the peer as first
* message. * message.
*/ */
public void runConnection(PeerListener listener, BitField bitfield) public void runConnection(I2PSnarkUtil util, PeerListener listener, BitField bitfield)
{ {
if (state != null) if (state != null)
throw new IllegalStateException("Peer already started"); throw new IllegalStateException("Peer already started");
@ -184,7 +184,7 @@ public class Peer implements Comparable
// Do we need to handshake? // Do we need to handshake?
if (din == null) if (din == null)
{ {
sock = I2PSnarkUtil.instance().connect(peerID); sock = util.connect(peerID);
_log.debug("Connected to " + peerID + ": " + sock); _log.debug("Connected to " + peerID + ": " + sock);
if ((sock == null) || (sock.isClosed())) { if ((sock == null) || (sock.isClosed())) {
throw new IOException("Unable to reach " + peerID); throw new IOException("Unable to reach " + peerID);

View File

@ -35,9 +35,11 @@ class PeerCheckerTask extends TimerTask
private static final long KILOPERSECOND = 1024*(PeerCoordinator.CHECK_PERIOD/1000); private static final long KILOPERSECOND = 1024*(PeerCoordinator.CHECK_PERIOD/1000);
private final PeerCoordinator coordinator; private final PeerCoordinator coordinator;
public I2PSnarkUtil _util;
PeerCheckerTask(PeerCoordinator coordinator) PeerCheckerTask(I2PSnarkUtil util, PeerCoordinator coordinator)
{ {
_util = util;
this.coordinator = coordinator; this.coordinator = coordinator;
} }
@ -102,8 +104,8 @@ class PeerCheckerTask extends TimerTask
peer.setRateHistory(upload, download); peer.setRateHistory(upload, download);
peer.resetCounters(); peer.resetCounters();
Snark.debug(peer + ":", Snark.DEBUG); _util.debug(peer + ":", Snark.DEBUG);
Snark.debug(" ul: " + upload/KILOPERSECOND _util.debug(" ul: " + upload/KILOPERSECOND
+ " dl: " + download/KILOPERSECOND + " dl: " + download/KILOPERSECOND
+ " i: " + peer.isInterested() + " i: " + peer.isInterested()
+ " I: " + peer.isInteresting() + " I: " + peer.isInteresting()
@ -129,7 +131,7 @@ class PeerCheckerTask extends TimerTask
// Check if it still wants pieces from us. // Check if it still wants pieces from us.
if (!peer.isInterested()) if (!peer.isInterested())
{ {
Snark.debug("Choke uninterested peer: " + peer, _util.debug("Choke uninterested peer: " + peer,
Snark.INFO); Snark.INFO);
peer.setChoking(true); peer.setChoking(true);
uploaders--; uploaders--;
@ -141,7 +143,7 @@ class PeerCheckerTask extends TimerTask
} }
else if (overBWLimitChoke) else if (overBWLimitChoke)
{ {
Snark.debug("BW limit (" + upload + "/" + uploaded + "), choke peer: " + peer, _util.debug("BW limit (" + upload + "/" + uploaded + "), choke peer: " + peer,
Snark.INFO); Snark.INFO);
peer.setChoking(true); peer.setChoking(true);
uploaders--; uploaders--;
@ -155,7 +157,7 @@ class PeerCheckerTask extends TimerTask
else if (peer.isInteresting() && peer.isChoked()) else if (peer.isInteresting() && peer.isChoked())
{ {
// If they are choking us make someone else a downloader // 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); peer.setChoking(true);
uploaders--; uploaders--;
coordinator.uploaders--; coordinator.uploaders--;
@ -168,7 +170,7 @@ class PeerCheckerTask extends TimerTask
else if (!peer.isInteresting() && !coordinator.completed()) else if (!peer.isInteresting() && !coordinator.completed())
{ {
// If they aren't interesting make someone else a downloader // 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); peer.setChoking(true);
uploaders--; uploaders--;
coordinator.uploaders--; coordinator.uploaders--;
@ -183,7 +185,7 @@ class PeerCheckerTask extends TimerTask
&& download == 0) && download == 0)
{ {
// We are downloading but didn't receive anything... // 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, Snark.DEBUG);
peer.setChoking(true); peer.setChoking(true);
uploaders--; uploaders--;
@ -222,7 +224,7 @@ class PeerCheckerTask extends TimerTask
|| uploaders > uploadLimit) || uploaders > uploadLimit)
&& worstDownloader != null) && worstDownloader != null)
{ {
Snark.debug("Choke worst downloader: " + worstDownloader, _util.debug("Choke worst downloader: " + worstDownloader,
Snark.DEBUG); Snark.DEBUG);
worstDownloader.setChoking(true); worstDownloader.setChoking(true);

View File

@ -77,13 +77,15 @@ public class PeerCoordinator implements PeerListener
private boolean halted = false; private boolean halted = false;
private final CoordinatorListener listener; private final CoordinatorListener listener;
public I2PSnarkUtil _util;
public String trackerProblems = null; public String trackerProblems = null;
public int trackerSeenPeers = 0; 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) CoordinatorListener listener, Snark torrent)
{ {
_util = util;
this.id = id; this.id = id;
this.metainfo = metainfo; this.metainfo = metainfo;
this.storage = storage; this.storage = storage;
@ -96,7 +98,7 @@ public class PeerCoordinator implements PeerListener
// Randomize the first start time so multiple tasks are spread out, // Randomize the first start time so multiple tasks are spread out,
// this will help the behavior with global limits // this will help the behavior with global limits
Random r = new Random(); 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 // only called externally from Storage after the double-check fails
@ -366,7 +368,7 @@ public class PeerCoordinator implements PeerListener
{ {
public void run() public void run()
{ {
peer.runConnection(listener, bitfield); peer.runConnection(_util, listener, bitfield);
} }
}; };
String threadName = peer.toString(); String threadName = peer.toString();
@ -846,7 +848,7 @@ public class PeerCoordinator implements PeerListener
*/ */
public int allowedUploaders() public int allowedUploaders()
{ {
if (Snark.overUploadLimit(uploaders)) { if (listener != null && listener.overUploadLimit(uploaders)) {
// if (_log.shouldLog(Log.DEBUG)) // if (_log.shouldLog(Log.DEBUG))
// _log.debug("Over limit, uploaders was: " + uploaders); // _log.debug("Over limit, uploaders was: " + uploaders);
return uploaders - 1; return uploaders - 1;
@ -858,12 +860,16 @@ public class PeerCoordinator implements PeerListener
public boolean overUpBWLimit() public boolean overUpBWLimit()
{ {
return Snark.overUpBWLimit(); if (listener != null)
return listener.overUpBWLimit();
return false;
} }
public boolean overUpBWLimit(long total) public boolean overUpBWLimit(long total)
{ {
return Snark.overUpBWLimit(total * 1000 / CHECK_PERIOD); if (listener != null)
return listener.overUpBWLimit(total * 1000 / CHECK_PERIOD);
return false;
} }
} }

View File

@ -12,11 +12,9 @@ import java.util.Set;
* from it there too) * from it there too)
*/ */
public class PeerCoordinatorSet { public class PeerCoordinatorSet {
private static final PeerCoordinatorSet _instance = new PeerCoordinatorSet();
public static final PeerCoordinatorSet instance() { return _instance; }
private Set _coordinators; private Set _coordinators;
private PeerCoordinatorSet() { public PeerCoordinatorSet() {
_coordinators = new HashSet(); _coordinators = new HashSet();
} }

View File

@ -72,7 +72,7 @@ public class PeerID implements Comparable
bevalue = (BEValue)m.get("ip"); bevalue = (BEValue)m.get("ip");
if (bevalue == null) if (bevalue == null)
throw new InvalidBEncodingException("ip missing"); throw new InvalidBEncodingException("ip missing");
address = I2PSnarkUtil.instance().getDestination(bevalue.getString()); address = I2PSnarkUtil.getDestinationFromBase64(bevalue.getString());
if (address == null) if (address == null)
throw new InvalidBEncodingException("Invalid destination [" + bevalue.getString() + "]"); throw new InvalidBEncodingException("Invalid destination [" + bevalue.getString() + "]");

View File

@ -34,6 +34,7 @@ import java.util.StringTokenizer;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import net.i2p.I2PAppContext;
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;
@ -102,7 +103,7 @@ public class Snark
public void outOfMemory(OutOfMemoryError err) { public void outOfMemory(OutOfMemoryError err) {
try { try {
err.printStackTrace(); err.printStackTrace();
I2PSnarkUtil.instance().debug("OOM in the snark", Snark.ERROR, err); System.out.println("OOM in the snark" + err);
} catch (Throwable t) { } catch (Throwable t) {
System.out.println("OOM in the OOM"); System.out.println("OOM in the OOM");
} }
@ -225,7 +226,7 @@ public class Snark
} }
catch(IOException ioe) catch(IOException ioe)
{ {
debug("ERROR while reading stdin: " + ioe, ERROR); System.out.println("ERROR while reading stdin: " + ioe);
} }
// Explicit shutdown. // Explicit shutdown.
@ -244,22 +245,34 @@ public class Snark
public CompleteListener completeListener; public CompleteListener completeListener;
public boolean stopped; public boolean stopped;
byte[] id; 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) { 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, StorageListener slistener, CoordinatorListener clistener,
CompleteListener complistener, boolean start, String rootDir) CompleteListener complistener, PeerCoordinatorSet peerCoordinatorSet,
ConnectionAcceptor connectionAcceptor, boolean start, String rootDir)
{ {
if (slistener == null) if (slistener == null)
slistener = this; slistener = this;
//if (clistener == null)
// clistener = this;
completeListener = complistener; completeListener = complistener;
_util = util;
_peerCoordinatorSet = peerCoordinatorSet;
acceptor = connectionAcceptor;
this.torrent = torrent; this.torrent = torrent;
this.rootDataDir = rootDir; this.rootDataDir = rootDir;
@ -292,7 +305,7 @@ public class Snark
while (i < 20) while (i < 20)
id[i++] = (byte)random.nextInt(256); 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; int port;
IOException lastException = null; IOException lastException = null;
@ -301,9 +314,9 @@ public class Snark
* If we are starting, * If we are starting,
* startTorrent() will force a connect. * startTorrent() will force a connect.
* *
boolean ok = I2PSnarkUtil.instance().connect(); boolean ok = util.connect();
if (!ok) fatal("Unable to connect to I2P"); if (!ok) fatal("Unable to connect to I2P");
I2PServerSocket serversocket = I2PSnarkUtil.instance().getServerSocket(); I2PServerSocket serversocket = util.getServerSocket();
if (serversocket == null) if (serversocket == null)
fatal("Unable to listen for I2P connections"); fatal("Unable to listen for I2P connections");
else { else {
@ -324,7 +337,7 @@ public class Snark
else else
{ {
activity = "Getting torrent"; activity = "Getting torrent";
File torrentFile = I2PSnarkUtil.instance().get(torrent, 3); File torrentFile = _util.get(torrent, 3);
if (torrentFile == null) { if (torrentFile == null) {
fatal("Unable to fetch " + torrent); fatal("Unable to fetch " + torrent);
if (false) return; // never reached - fatal(..) throws if (false) return; // never reached - fatal(..) throws
@ -348,7 +361,7 @@ public class Snark
/* /*
{ {
// Try to create a new metainfo file // Try to create a new metainfo file
Snark.debug debug
("Trying to create metainfo torrent for '" + torrent + "'", ("Trying to create metainfo torrent for '" + torrent + "'",
NOTICE); NOTICE);
try try
@ -381,7 +394,7 @@ public class Snark
try try
{ {
activity = "Checking storage"; activity = "Checking storage";
storage = new Storage(meta, slistener); storage = new Storage(_util, meta, slistener);
if (completeListener != null) { if (completeListener != null) {
storage.check(rootDataDir, storage.check(rootDataDir,
completeListener.getSavedTorrentTime(this), completeListener.getSavedTorrentTime(this),
@ -422,10 +435,10 @@ public class Snark
* Start up contacting peers and querying the tracker * Start up contacting peers and querying the tracker
*/ */
public void startTorrent() { public void startTorrent() {
boolean ok = I2PSnarkUtil.instance().connect(); boolean ok = _util.connect();
if (!ok) fatal("Unable to connect to I2P"); if (!ok) fatal("Unable to connect to I2P");
if (coordinator == null) { if (coordinator == null) {
I2PServerSocket serversocket = I2PSnarkUtil.instance().getServerSocket(); I2PServerSocket serversocket = _util.getServerSocket();
if (serversocket == null) if (serversocket == null)
fatal("Unable to listen for I2P connections"); fatal("Unable to listen for I2P connections");
else { else {
@ -434,12 +447,20 @@ public class Snark
} }
debug("Starting PeerCoordinator, ConnectionAcceptor, and TrackerClient", NOTICE); debug("Starting PeerCoordinator, ConnectionAcceptor, and TrackerClient", NOTICE);
activity = "Collecting pieces"; activity = "Collecting pieces";
coordinator = new PeerCoordinator(id, meta, storage, this, this); coordinator = new PeerCoordinator(_util, id, meta, storage, this, this);
PeerCoordinatorSet set = PeerCoordinatorSet.instance(); if (_peerCoordinatorSet != null) {
set.add(coordinator); // multitorrent
ConnectionAcceptor acceptor = ConnectionAcceptor.instance(); _peerCoordinatorSet.add(coordinator);
acceptor.startAccepting(set, serversocket); if (acceptor != null) {
trackerclient = new TrackerClient(meta, coordinator); 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; stopped = false;
@ -447,11 +468,12 @@ public class Snark
if (coordinator.halted()) { if (coordinator.halted()) {
// ok, we have already started and stopped, but the coordinator seems a bit annoying to // 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 // restart safely, so lets build a new one to replace the old
PeerCoordinatorSet set = PeerCoordinatorSet.instance(); if (_peerCoordinatorSet != null)
set.remove(coordinator); _peerCoordinatorSet.remove(coordinator);
PeerCoordinator newCoord = new PeerCoordinator(coordinator.getID(), coordinator.getMetaInfo(), PeerCoordinator newCoord = new PeerCoordinator(_util, coordinator.getID(), coordinator.getMetaInfo(),
coordinator.getStorage(), coordinator.getListener(), this); coordinator.getStorage(), coordinator.getListener(), this);
set.add(newCoord); if (_peerCoordinatorSet != null)
_peerCoordinatorSet.add(newCoord);
coordinator = newCoord; coordinator = newCoord;
coordinatorChanged = true; coordinatorChanged = true;
} }
@ -469,7 +491,7 @@ public class Snark
} }
fatal("Could not reopen storage", ioe); fatal("Could not reopen storage", ioe);
} }
TrackerClient newClient = new TrackerClient(coordinator.getMetaInfo(), coordinator); TrackerClient newClient = new TrackerClient(_util, coordinator.getMetaInfo(), coordinator);
if (!trackerclient.halted()) if (!trackerclient.halted())
trackerclient.halt(); trackerclient.halt();
trackerclient = newClient; trackerclient = newClient;
@ -499,8 +521,8 @@ public class Snark
if (changed && completeListener != null) if (changed && completeListener != null)
completeListener.updateStatus(this); completeListener.updateStatus(this);
} }
if (pc != null) if (pc != null && _peerCoordinatorSet != null)
PeerCoordinatorSet.instance().remove(pc); _peerCoordinatorSet.remove(pc);
} }
static Snark parseArguments(String[] args) static Snark parseArguments(String[] args)
@ -522,7 +544,8 @@ public class Snark
String ip = null; String ip = null;
String torrent = null; String torrent = null;
boolean configured = I2PSnarkUtil.instance().configured(); I2PSnarkUtil util = new I2PSnarkUtil(I2PAppContext.getGlobalContext());
boolean configured = util.configured();
int i = 0; int i = 0;
while (i < args.length) while (i < args.length)
@ -572,7 +595,7 @@ public class Snark
String proxyHost = args[i+1]; String proxyHost = args[i+1];
String proxyPort = args[i+2]; String proxyPort = args[i+2];
if (!configured) if (!configured)
I2PSnarkUtil.instance().setProxy(proxyHost, Integer.parseInt(proxyPort)); util.setProxy(proxyHost, Integer.parseInt(proxyPort));
i += 3; i += 3;
} }
else if (args[i].equals("--i2cp")) else if (args[i].equals("--i2cp"))
@ -594,7 +617,7 @@ public class Snark
} }
} }
if (!configured) if (!configured)
I2PSnarkUtil.instance().setI2CPConfig(i2cpHost, Integer.parseInt(i2cpPort), opts); util.setI2CPConfig(i2cpHost, Integer.parseInt(i2cpPort), opts);
i += 3 + (opts != null ? 1 : 0); i += 3 + (opts != null ? 1 : 0);
} }
else else
@ -611,7 +634,7 @@ public class Snark
else else
usage("Need exactly one <url>, <file> or <dir>."); 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) private static void usage(String s)
@ -678,7 +701,7 @@ public class Snark
*/ */
public void fatal(String s, Throwable t) 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))); //System.err.println("snark: " + s + ((t == null) ? "" : (": " + t)));
//if (debug >= INFO && t != null) //if (debug >= INFO && t != null)
// t.printStackTrace(); // t.printStackTrace();
@ -689,13 +712,12 @@ public class Snark
/** /**
* Show debug info if debug is true. * 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); _util.debug(s, level, null);
//if (debug >= level)
// System.out.println(s);
} }
/** coordinatorListener */
public void peerChange(PeerCoordinator coordinator, Peer peer) public void peerChange(PeerCoordinator coordinator, Peer peer)
{ {
// System.out.println(peer.toString()); // System.out.println(peer.toString());
@ -742,7 +764,7 @@ public class Snark
checking = true; checking = true;
} }
if (!checking) if (!checking)
Snark.debug("Got " + (checked ? "" : "BAD ") + "piece: " + num, debug("Got " + (checked ? "" : "BAD ") + "piece: " + num,
Snark.INFO); Snark.INFO);
} }
@ -759,7 +781,7 @@ public class Snark
public void storageCompleted(Storage storage) public void storageCompleted(Storage storage)
{ {
Snark.debug("Completely received " + torrent, Snark.INFO); debug("Completely received " + torrent, Snark.INFO);
//storage.close(); //storage.close();
//System.out.println("Completely received: " + torrent); //System.out.println("Completely received: " + torrent);
if (completeListener != null) if (completeListener != null)
@ -787,41 +809,40 @@ public class Snark
} }
/** Maintain a configurable total uploader cap /** Maintain a configurable total uploader cap
* coordinatorListener
*/ */
final static int MIN_TOTAL_UPLOADERS = 4; final static int MIN_TOTAL_UPLOADERS = 4;
final static int MAX_TOTAL_UPLOADERS = 10; final static int MAX_TOTAL_UPLOADERS = 10;
public static boolean overUploadLimit(int uploaders) { public boolean overUploadLimit(int uploaders) {
PeerCoordinatorSet coordinators = PeerCoordinatorSet.instance(); if (_peerCoordinatorSet == null || uploaders <= 0)
if (coordinators == null || uploaders <= 0)
return false; return false;
int totalUploaders = 0; int totalUploaders = 0;
for (Iterator iter = coordinators.iterator(); iter.hasNext(); ) { for (Iterator iter = _peerCoordinatorSet.iterator(); iter.hasNext(); ) {
PeerCoordinator c = (PeerCoordinator)iter.next(); PeerCoordinator c = (PeerCoordinator)iter.next();
if (!c.halted()) if (!c.halted())
totalUploaders += c.uploaders; totalUploaders += c.uploaders;
} }
int limit = I2PSnarkUtil.instance().getMaxUploaders(); int limit = _util.getMaxUploaders();
// Snark.debug("Total uploaders: " + totalUploaders + " Limit: " + limit, Snark.DEBUG); // debug("Total uploaders: " + totalUploaders + " Limit: " + limit, Snark.DEBUG);
return totalUploaders > limit; return totalUploaders > limit;
} }
public static boolean overUpBWLimit() { public boolean overUpBWLimit() {
PeerCoordinatorSet coordinators = PeerCoordinatorSet.instance(); if (_peerCoordinatorSet == null)
if (coordinators == null)
return false; return false;
long total = 0; long total = 0;
for (Iterator iter = coordinators.iterator(); iter.hasNext(); ) { for (Iterator iter = _peerCoordinatorSet.iterator(); iter.hasNext(); ) {
PeerCoordinator c = (PeerCoordinator)iter.next(); PeerCoordinator c = (PeerCoordinator)iter.next();
if (!c.halted()) if (!c.halted())
total += c.getCurrentUploadRate(); total += c.getCurrentUploadRate();
} }
long limit = 1024l * I2PSnarkUtil.instance().getMaxUpBW(); long limit = 1024l * _util.getMaxUpBW();
Snark.debug("Total up bw: " + total + " Limit: " + limit, Snark.WARNING); debug("Total up bw: " + total + " Limit: " + limit, Snark.WARNING);
return total > limit; return total > limit;
} }
public static boolean overUpBWLimit(long total) { public boolean overUpBWLimit(long total) {
long limit = 1024l * I2PSnarkUtil.instance().getMaxUpBW(); long limit = 1024l * _util.getMaxUpBW();
return total > limit; return total > limit;
} }
} }

View File

@ -37,6 +37,9 @@ public class SnarkManager implements Snark.CompleteListener {
private I2PAppContext _context; private I2PAppContext _context;
private Log _log; private Log _log;
private List _messages; 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_HOST = "i2psnark.i2cpHost";
public static final String PROP_I2CP_PORT = "i2psnark.i2cpPort"; public static final String PROP_I2CP_PORT = "i2psnark.i2cpPort";
@ -63,6 +66,9 @@ public class SnarkManager implements Snark.CompleteListener {
_context = I2PAppContext.getGlobalContext(); _context = I2PAppContext.getGlobalContext();
_log = _context.logManager().getLog(SnarkManager.class); _log = _context.logManager().getLog(SnarkManager.class);
_messages = new ArrayList(16); _messages = new ArrayList(16);
_util = new I2PSnarkUtil(_context);
_peerCoordinatorSet = new PeerCoordinatorSet();
_connectionAcceptor = new ConnectionAcceptor(_util);
loadConfig("i2psnark.config"); 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"));
@ -73,6 +79,9 @@ public class SnarkManager implements Snark.CompleteListener {
((RouterContext)_context).router().addShutdownTask(new SnarkManagerShutdown()); ((RouterContext)_context).router().addShutdownTask(new SnarkManagerShutdown());
} }
/** hook to I2PSnarkUtil for the servlet */
public I2PSnarkUtil util() { return _util; }
private static final int MAX_MESSAGES = 5; private static final int MAX_MESSAGES = 5;
public void addMessage(String message) { public void addMessage(String message) {
synchronized (_messages) { synchronized (_messages) {
@ -162,16 +171,16 @@ public class SnarkManager implements Snark.CompleteListener {
} }
} }
if (i2cpHost != null) { if (i2cpHost != null) {
I2PSnarkUtil.instance().setI2CPConfig(i2cpHost, i2cpPort, i2cpOpts); _util.setI2CPConfig(i2cpHost, i2cpPort, i2cpOpts);
_log.debug("Configuring with I2CP options " + i2cpOpts); _log.debug("Configuring with I2CP options " + i2cpOpts);
} }
//I2PSnarkUtil.instance().setI2CPConfig("66.111.51.110", 7654, new Properties()); //I2PSnarkUtil.instance().setI2CPConfig("66.111.51.110", 7654, new Properties());
String eepHost = _config.getProperty(PROP_EEP_HOST); String eepHost = _config.getProperty(PROP_EEP_HOST);
int eepPort = getInt(PROP_EEP_PORT, 4444); int eepPort = getInt(PROP_EEP_PORT, 4444);
if (eepHost != null) if (eepHost != null)
I2PSnarkUtil.instance().setProxy(eepHost, eepPort); _util.setProxy(eepHost, eepPort);
I2PSnarkUtil.instance().setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS)); _util.setMaxUploaders(getInt(PROP_UPLOADERS_TOTAL, Snark.MAX_TOTAL_UPLOADERS));
I2PSnarkUtil.instance().setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW)); _util.setMaxUpBW(getInt(PROP_UPBW_MAX, DEFAULT_MAX_UP_BW));
getDataDir().mkdirs(); getDataDir().mkdirs();
} }
@ -191,12 +200,12 @@ public class SnarkManager implements Snark.CompleteListener {
String upLimit, String upBW, boolean useOpenTrackers, String openTrackers) { String upLimit, String upBW, boolean useOpenTrackers, String openTrackers) {
boolean changed = false; boolean changed = false;
if (eepHost != null) { if (eepHost != null) {
int port = I2PSnarkUtil.instance().getEepProxyPort(); int port = _util.getEepProxyPort();
try { port = Integer.parseInt(eepPort); } catch (NumberFormatException nfe) {} try { port = Integer.parseInt(eepPort); } catch (NumberFormatException nfe) {}
String host = I2PSnarkUtil.instance().getEepProxyHost(); String host = _util.getEepProxyHost();
if ( (eepHost.trim().length() > 0) && (port > 0) && if ( (eepHost.trim().length() > 0) && (port > 0) &&
((!host.equals(eepHost) || (port != I2PSnarkUtil.instance().getEepProxyPort()) )) ) { ((!host.equals(eepHost) || (port != _util.getEepProxyPort()) )) ) {
I2PSnarkUtil.instance().setProxy(eepHost, port); _util.setProxy(eepHost, port);
changed = true; changed = true;
_config.setProperty(PROP_EEP_HOST, eepHost); _config.setProperty(PROP_EEP_HOST, eepHost);
_config.setProperty(PROP_EEP_PORT, eepPort+""); _config.setProperty(PROP_EEP_PORT, eepPort+"");
@ -204,11 +213,11 @@ public class SnarkManager implements Snark.CompleteListener {
} }
} }
if (upLimit != null) { if (upLimit != null) {
int limit = I2PSnarkUtil.instance().getMaxUploaders(); int limit = _util.getMaxUploaders();
try { limit = Integer.parseInt(upLimit); } catch (NumberFormatException nfe) {} try { limit = Integer.parseInt(upLimit); } catch (NumberFormatException nfe) {}
if ( limit != I2PSnarkUtil.instance().getMaxUploaders()) { if ( limit != _util.getMaxUploaders()) {
if ( limit >= Snark.MIN_TOTAL_UPLOADERS ) { if ( limit >= Snark.MIN_TOTAL_UPLOADERS ) {
I2PSnarkUtil.instance().setMaxUploaders(limit); _util.setMaxUploaders(limit);
changed = true; changed = true;
_config.setProperty(PROP_UPLOADERS_TOTAL, "" + limit); _config.setProperty(PROP_UPLOADERS_TOTAL, "" + limit);
addMessage("Total uploaders limit changed to " + limit); addMessage("Total uploaders limit changed to " + limit);
@ -218,11 +227,11 @@ public class SnarkManager implements Snark.CompleteListener {
} }
} }
if (upBW != null) { if (upBW != null) {
int limit = I2PSnarkUtil.instance().getMaxUpBW(); int limit = _util.getMaxUpBW();
try { limit = Integer.parseInt(upBW); } catch (NumberFormatException nfe) {} try { limit = Integer.parseInt(upBW); } catch (NumberFormatException nfe) {}
if ( limit != I2PSnarkUtil.instance().getMaxUpBW()) { if ( limit != _util.getMaxUpBW()) {
if ( limit >= MIN_UP_BW ) { if ( limit >= MIN_UP_BW ) {
I2PSnarkUtil.instance().setMaxUpBW(limit); _util.setMaxUpBW(limit);
changed = true; changed = true;
_config.setProperty(PROP_UPBW_MAX, "" + limit); _config.setProperty(PROP_UPBW_MAX, "" + limit);
addMessage("Up BW limit changed to " + limit + "KBps"); addMessage("Up BW limit changed to " + limit + "KBps");
@ -232,8 +241,8 @@ public class SnarkManager implements Snark.CompleteListener {
} }
} }
if (i2cpHost != null) { if (i2cpHost != null) {
int oldI2CPPort = I2PSnarkUtil.instance().getI2CPPort(); int oldI2CPPort = _util.getI2CPPort();
String oldI2CPHost = I2PSnarkUtil.instance().getI2CPHost(); String oldI2CPHost = _util.getI2CPHost();
int port = oldI2CPPort; int port = oldI2CPPort;
try { port = Integer.parseInt(i2cpPort); } catch (NumberFormatException nfe) {} try { port = Integer.parseInt(i2cpPort); } catch (NumberFormatException nfe) {}
String host = oldI2CPHost; String host = oldI2CPHost;
@ -259,7 +268,7 @@ public class SnarkManager implements Snark.CompleteListener {
if ( (i2cpHost.trim().length() > 0) && (port > 0) && if ( (i2cpHost.trim().length() > 0) && (port > 0) &&
((!host.equals(i2cpHost) || ((!host.equals(i2cpHost) ||
(port != I2PSnarkUtil.instance().getI2CPPort()) || (port != _util.getI2CPPort()) ||
(!oldOpts.equals(opts)))) ) { (!oldOpts.equals(opts)))) ) {
boolean snarksActive = false; boolean snarksActive = false;
Set names = listTorrentFiles(); Set names = listTorrentFiles();
@ -275,19 +284,19 @@ public class SnarkManager implements Snark.CompleteListener {
_log.debug("i2cp host [" + i2cpHost + "] i2cp port " + port + " opts [" + opts _log.debug("i2cp host [" + i2cpHost + "] i2cp port " + port + " opts [" + opts
+ "] oldOpts [" + oldOpts + "]"); + "] oldOpts [" + oldOpts + "]");
} else { } else {
if (I2PSnarkUtil.instance().connected()) { if (_util.connected()) {
I2PSnarkUtil.instance().disconnect(); _util.disconnect();
addMessage("Disconnecting old I2CP destination"); addMessage("Disconnecting old I2CP destination");
} }
Properties p = new Properties(); Properties p = new Properties();
p.putAll(opts); p.putAll(opts);
addMessage("I2CP settings changed to " + i2cpHost + ":" + port + " (" + i2cpOpts.trim() + ")"); addMessage("I2CP settings changed to " + i2cpHost + ":" + port + " (" + i2cpOpts.trim() + ")");
I2PSnarkUtil.instance().setI2CPConfig(i2cpHost, port, p); _util.setI2CPConfig(i2cpHost, port, p);
boolean ok = I2PSnarkUtil.instance().connect(); boolean ok = _util.connect();
if (!ok) { if (!ok) {
addMessage("Unable to connect with the new settings, reverting to the old I2CP settings"); addMessage("Unable to connect with the new settings, reverting to the old I2CP settings");
I2PSnarkUtil.instance().setI2CPConfig(oldI2CPHost, oldI2CPPort, oldOpts); _util.setI2CPConfig(oldI2CPHost, oldI2CPPort, oldOpts);
ok = I2PSnarkUtil.instance().connect(); ok = _util.connect();
if (!ok) if (!ok)
addMessage("Unable to reconnect with the old settings!"); addMessage("Unable to reconnect with the old settings!");
} else { } else {
@ -315,13 +324,13 @@ public class SnarkManager implements Snark.CompleteListener {
addMessage("Adjusted autostart to " + autoStart); addMessage("Adjusted autostart to " + autoStart);
changed = true; changed = true;
} }
if (I2PSnarkUtil.instance().shouldUseOpenTrackers() != useOpenTrackers) { if (_util.shouldUseOpenTrackers() != useOpenTrackers) {
_config.setProperty(I2PSnarkUtil.PROP_USE_OPENTRACKERS, useOpenTrackers + ""); _config.setProperty(I2PSnarkUtil.PROP_USE_OPENTRACKERS, useOpenTrackers + "");
addMessage((useOpenTrackers ? "En" : "Dis") + "abled open trackers - torrent restart required to take effect"); addMessage((useOpenTrackers ? "En" : "Dis") + "abled open trackers - torrent restart required to take effect");
changed = true; changed = true;
} }
if (openTrackers != null) { 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()); _config.setProperty(I2PSnarkUtil.PROP_OPENTRACKERS, openTrackers.trim());
addMessage("Open Tracker list changed - torrent restart required to take effect"); addMessage("Open Tracker list changed - torrent restart required to take effect");
changed = true; 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 Snark getTorrent(String filename) { synchronized (_snarks) { return (Snark)_snarks.get(filename); } }
public void addTorrent(String filename) { addTorrent(filename, false); } public void addTorrent(String filename) { addTorrent(filename, false); }
public void addTorrent(String filename, boolean dontAutoStart) { public void addTorrent(String filename, boolean dontAutoStart) {
if ((!dontAutoStart) && !I2PSnarkUtil.instance().connected()) { if ((!dontAutoStart) && !_util.connected()) {
addMessage("Connecting to I2P"); addMessage("Connecting to I2P");
boolean ok = I2PSnarkUtil.instance().connect(); boolean ok = _util.connect();
if (!ok) { if (!ok) {
addMessage("Error connecting to I2P - check your I2CP settings"); addMessage("Error connecting to I2P - check your I2CP settings");
return; return;
@ -400,7 +409,9 @@ public class SnarkManager implements Snark.CompleteListener {
addMessage(rejectMessage); addMessage(rejectMessage);
return; return;
} else { } 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; torrent.completeListener = this;
synchronized (_snarks) { synchronized (_snarks) {
_snarks.put(filename, torrent); _snarks.put(filename, torrent);
@ -569,7 +580,7 @@ public class SnarkManager implements Snark.CompleteListener {
if (remaining == 0) { if (remaining == 0) {
// should we disconnect/reconnect here (taking care to deal with the other thread's // should we disconnect/reconnect here (taking care to deal with the other thread's
// I2PServerSocket.accept() call properly?) // I2PServerSocket.accept() call properly?)
////I2PSnarkUtil.instance(). ////_util.
} }
if (!wasStopped) if (!wasStopped)
addMessage("Torrent stopped: '" + sfile.getName() + "'"); addMessage("Torrent stopped: '" + sfile.getName() + "'");
@ -645,7 +656,7 @@ public class SnarkManager implements Snark.CompleteListener {
if (existingNames.contains(foundNames.get(i))) { if (existingNames.contains(foundNames.get(i))) {
// already known. noop // already known. noop
} else { } else {
if (shouldAutoStart() && !I2PSnarkUtil.instance().connect()) if (shouldAutoStart() && !_util.connect())
addMessage("Unable to connect to I2P"); addMessage("Unable to connect to I2P");
addTorrent((String)foundNames.get(i), !shouldAutoStart()); addTorrent((String)foundNames.get(i), !shouldAutoStart());
} }

View File

@ -51,21 +51,21 @@ public class SnarkShutdown extends I2PThread
public void run() 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) if (acceptor != null)
acceptor.halt(); acceptor.halt();
Snark.debug("Halting TrackerClient...", Snark.INFO); //Snark.debug("Halting TrackerClient...", Snark.INFO);
if (trackerclient != null) if (trackerclient != null)
trackerclient.halt(); trackerclient.halt();
Snark.debug("Halting PeerCoordinator...", Snark.INFO); //Snark.debug("Halting PeerCoordinator...", Snark.INFO);
if (coordinator != null) if (coordinator != null)
coordinator.halt(); coordinator.halt();
Snark.debug("Closing Storage...", Snark.INFO); //Snark.debug("Closing Storage...", Snark.INFO);
if (storage != null) if (storage != null)
{ {
try try
@ -74,7 +74,7 @@ public class SnarkShutdown extends I2PThread
} }
catch(IOException ioe) 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"); throw new RuntimeException("b0rking");
} }
} }
@ -82,7 +82,7 @@ public class SnarkShutdown extends I2PThread
// XXX - Should actually wait till done... // XXX - Should actually wait till done...
try try
{ {
Snark.debug("Waiting 5 seconds...", Snark.INFO); //Snark.debug("Waiting 5 seconds...", Snark.INFO);
Thread.sleep(5*1000); Thread.sleep(5*1000);
} }
catch (InterruptedException ie) { /* ignored */ } catch (InterruptedException ie) { /* ignored */ }

View File

@ -44,6 +44,7 @@ public class Storage
private File[] RAFfile; // File to make it easier to reopen private File[] RAFfile; // File to make it easier to reopen
private final StorageListener listener; private final StorageListener listener;
private I2PSnarkUtil _util;
private BitField bitfield; // BitField to represent the pieces private BitField bitfield; // BitField to represent the pieces
private int needed; // Number of pieces needed private int needed; // Number of pieces needed
@ -66,9 +67,10 @@ public class Storage
* *
* @exception IOException when creating and/or checking files fails. * @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 throws IOException
{ {
_util = util;
this.metainfo = metainfo; this.metainfo = metainfo;
this.listener = listener; this.listener = listener;
needed = metainfo.getPieces(); needed = metainfo.getPieces();
@ -81,9 +83,10 @@ public class Storage
* with an appropriate MetaInfo file as can be announced on the * with an appropriate MetaInfo file as can be announced on the
* given announce String location. * given announce String location.
*/ */
public Storage(File baseFile, String announce, StorageListener listener) public Storage(I2PSnarkUtil util, File baseFile, String announce, StorageListener listener)
throws IOException throws IOException
{ {
_util = util;
this.listener = listener; this.listener = listener;
// Create names, rafs and lengths arrays. // Create names, rafs and lengths arrays.
getFiles(baseFile); 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()) if (!f.isDirectory())
l.add(f); l.add(f);
@ -245,7 +248,7 @@ public class Storage
File[] files = f.listFiles(); File[] files = f.listFiles();
if (files == null) if (files == null)
{ {
Snark.debug("WARNING: Skipping '" + f _util.debug("WARNING: Skipping '" + f
+ "' not a normal file.", Snark.WARNING); + "' not a normal file.", Snark.WARNING);
return; return;
} }
@ -305,7 +308,7 @@ public class Storage
if (files == null) if (files == null)
{ {
// Create base as file. // 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()) if (!base.createNewFile() && !base.exists())
throw new IOException("Could not create file " + base); throw new IOException("Could not create file " + base);
@ -328,7 +331,7 @@ public class Storage
else else
{ {
// Create base as dir. // 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()) if (!base.mkdir() && !base.isDirectory())
throw new IOException("Could not create directory " + base); throw new IOException("Could not create directory " + base);
@ -366,16 +369,16 @@ public class Storage
bitfield = savedBitField; bitfield = savedBitField;
needed = metainfo.getPieces() - bitfield.count(); needed = metainfo.getPieces() - bitfield.count();
_probablyComplete = complete(); _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 { } else {
// the following sets the needed variable // the following sets the needed variable
changed = true; changed = true;
checkCreateFiles(); checkCreateFiles();
} }
if (complete()) if (complete())
Snark.debug("Torrent is complete", Snark.NOTICE); _util.debug("Torrent is complete", Snark.NOTICE);
else 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) if (files == null)
{ {
// Reopen base as file. // Reopen base as file.
Snark.debug("Reopening file: " + base, Snark.NOTICE); _util.debug("Reopening file: " + base, Snark.NOTICE);
if (!base.exists()) if (!base.exists())
throw new IOException("Could not reopen file " + base); throw new IOException("Could not reopen file " + base);
} }
else else
{ {
// Reopen base as dir. // Reopen base as dir.
Snark.debug("Reopening directory: " + base, Snark.NOTICE); _util.debug("Reopening directory: " + base, Snark.NOTICE);
if (!base.isDirectory()) if (!base.isDirectory())
throw new IOException("Could not reopen directory " + base); throw new IOException("Could not reopen directory " + base);
@ -487,7 +490,7 @@ public class Storage
allocateFile(i); allocateFile(i);
} }
} else { } 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; changed = true;
_probablyComplete = false; // to force RW _probablyComplete = false; // to force RW
synchronized(RAFlock[i]) { synchronized(RAFlock[i]) {
@ -574,7 +577,7 @@ public class Storage
closeRAF(i); closeRAF(i);
} }
} catch (IOException ioe) { } catch (IOException ioe) {
I2PSnarkUtil.instance().debug("Error closing " + RAFfile[i], Snark.ERROR, ioe); _util.debug("Error closing " + RAFfile[i], Snark.ERROR, ioe);
// gobble gobble // gobble gobble
} }
} }
@ -595,7 +598,7 @@ public class Storage
try { try {
bs = new byte[len]; bs = new byte[len];
} catch (OutOfMemoryError oom) { } 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; return null;
} }
getUncheckedPiece(piece, bs, off, len); getUncheckedPiece(piece, bs, off, len);
@ -691,7 +694,7 @@ public class Storage
if (needed > 0) { if (needed > 0) {
if (listener != null) if (listener != null)
listener.setWantedPieces(this); listener.setWantedPieces(this);
Snark.debug("WARNING: Not really done, missing " + needed _util.debug("WARNING: Not really done, missing " + needed
+ " pieces", Snark.WARNING); + " pieces", Snark.WARNING);
} else { } else {
if (listener != null) if (listener != null)

View File

@ -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 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 final static int LONG_SLEEP = 30*60*1000; // sleep a while after lots of fails
private I2PSnarkUtil _util;
private final MetaInfo meta; private final MetaInfo meta;
private final PeerCoordinator coordinator; private final PeerCoordinator coordinator;
private final int port; private final int port;
@ -66,10 +67,11 @@ public class TrackerClient extends I2PThread
private List trackers; private List trackers;
public TrackerClient(MetaInfo meta, PeerCoordinator coordinator) public TrackerClient(I2PSnarkUtil util, MetaInfo meta, PeerCoordinator coordinator)
{ {
// Set unique name. // Set unique name.
super("TrackerClient-" + urlencode(coordinator.getID())); super("TrackerClient-" + urlencode(coordinator.getID()));
_util = util;
this.meta = meta; this.meta = meta;
this.coordinator = coordinator; this.coordinator = coordinator;
@ -98,13 +100,13 @@ public class TrackerClient extends I2PThread
} }
private boolean verifyConnected() { private boolean verifyConnected() {
while (!stop && !I2PSnarkUtil.instance().connected()) { while (!stop && !_util.connected()) {
boolean ok = I2PSnarkUtil.instance().connect(); boolean ok = _util.connect();
if (!ok) { if (!ok) {
try { Thread.sleep(30*1000); } catch (InterruptedException ie) {} try { Thread.sleep(30*1000); } catch (InterruptedException ie) {}
} }
} }
return !stop && I2PSnarkUtil.instance().connected(); return !stop && _util.connected();
} }
public void run() public void run()
@ -121,7 +123,7 @@ public class TrackerClient extends I2PThread
// the primary tracker, that we don't add it twice. // the primary tracker, that we don't add it twice.
trackers = new ArrayList(2); trackers = new ArrayList(2);
trackers.add(new Tracker(meta.getAnnounce(), true)); trackers.add(new Tracker(meta.getAnnounce(), true));
List tlist = I2PSnarkUtil.instance().getOpenTrackers(); List tlist = _util.getOpenTrackers();
if (tlist != null) { if (tlist != null) {
for (int i = 0; i < tlist.size(); i++) { for (int i = 0; i < tlist.size(); i++) {
String url = (String)tlist.get(i); String url = (String)tlist.get(i);
@ -136,7 +138,7 @@ public class TrackerClient extends I2PThread
} }
if (meta.getAnnounce().startsWith(url.substring(0, slash))) if (meta.getAnnounce().startsWith(url.substring(0, slash)))
continue; continue;
String dest = I2PSnarkUtil.instance().lookup(url.substring(7, slash)); String dest = _util.lookup(url.substring(7, slash));
if (dest == null) { if (dest == null) {
_log.error("Announce host unknown: [" + url + "]"); _log.error("Announce host unknown: [" + url + "]");
continue; continue;
@ -264,7 +266,7 @@ public class TrackerClient extends I2PThread
catch (IOException ioe) catch (IOException ioe)
{ {
// Probably not fatal (if it doesn't last to long...) // Probably not fatal (if it doesn't last to long...)
Snark.debug _util.debug
("WARNING: Could not contact tracker at '" ("WARNING: Could not contact tracker at '"
+ tr.announce + "': " + ioe, Snark.WARNING); + tr.announce + "': " + ioe, Snark.WARNING);
tr.trackerProblems = ioe.getMessage(); 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 // we could try and total the unique peers but that's too hard for now
coordinator.trackerSeenPeers = maxSeenPeers; coordinator.trackerSeenPeers = maxSeenPeers;
if (!started) if (!started)
Snark.debug(" Retrying in one minute...", Snark.DEBUG); _util.debug(" Retrying in one minute...", Snark.DEBUG);
} // *** end of while loop } // *** end of while loop
} // try } // try
catch (Throwable t) catch (Throwable t)
{ {
I2PSnarkUtil.instance().debug("TrackerClient: " + t, Snark.ERROR, t); _util.debug("TrackerClient: " + t, Snark.ERROR, t);
if (t instanceof OutOfMemoryError) if (t instanceof OutOfMemoryError)
throw (OutOfMemoryError)t; throw (OutOfMemoryError)t;
} }
@ -332,15 +334,15 @@ public class TrackerClient extends I2PThread
+ "?info_hash=" + infoHash + "?info_hash=" + infoHash
+ "&peer_id=" + peerID + "&peer_id=" + peerID
+ "&port=" + port + "&port=" + port
+ "&ip=" + I2PSnarkUtil.instance().getOurIPString() + ".i2p" + "&ip=" + _util.getOurIPString() + ".i2p"
+ "&uploaded=" + uploaded + "&uploaded=" + uploaded
+ "&downloaded=" + downloaded + "&downloaded=" + downloaded
+ "&left=" + left + "&left=" + left
+ ((event != NO_EVENT) ? ("&event=" + event) : ""); + ((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(); tr.lastRequestTime = System.currentTimeMillis();
File fetched = I2PSnarkUtil.instance().get(s); File fetched = _util.get(s);
if (fetched == null) { if (fetched == null) {
throw new IOException("Error fetching " + s); throw new IOException("Error fetching " + s);
} }
@ -352,7 +354,7 @@ public class TrackerClient extends I2PThread
TrackerInfo info = new TrackerInfo(in, coordinator.getID(), TrackerInfo info = new TrackerInfo(in, coordinator.getID(),
coordinator.getMetaInfo()); coordinator.getMetaInfo());
Snark.debug("TrackerClient response: " + info, Snark.INFO); _util.debug("TrackerClient response: " + info, Snark.INFO);
String failure = info.getFailureReason(); String failure = info.getFailureReason();
if (failure != null) if (failure != null)

View File

@ -101,7 +101,7 @@ public class TrackerInfo
peerID = new PeerID(((BEValue)it.next()).getMap()); peerID = new PeerID(((BEValue)it.next()).getMap());
} catch (InvalidBEncodingException ibe) { } catch (InvalidBEncodingException ibe) {
// don't let one bad entry spoil the whole list // 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; continue;
} }
peers.add(new Peer(peerID, my_id, metainfo)); peers.add(new Peer(peerID, my_id, metainfo));

View File

@ -116,7 +116,7 @@ public class I2PSnarkServlet extends HttpServlet {
List snarks = getSortedSnarks(req); List snarks = getSortedSnarks(req);
String uri = req.getRequestURI(); String uri = req.getRequestURI();
out.write(TABLE_HEADER); out.write(TABLE_HEADER);
if (I2PSnarkUtil.instance().connected() && snarks.size() > 0) { if (_manager.util().connected() && snarks.size() > 0) {
if (peerParam != null) if (peerParam != null)
out.write("(<a href=\"" + req.getRequestURI() + "\">Hide Peers</a>)<br />\n"); out.write("(<a href=\"" + req.getRequestURI() + "\">Hide Peers</a>)<br />\n");
else else
@ -124,7 +124,7 @@ public class I2PSnarkServlet extends HttpServlet {
} }
out.write(TABLE_HEADER2); out.write(TABLE_HEADER2);
out.write("<th align=\"left\" valign=\"top\">"); out.write("<th align=\"left\" valign=\"top\">");
if (I2PSnarkUtil.instance().connected()) if (_manager.util().connected())
out.write("<a href=\"" + uri + "?action=StopAll&nonce=" + _nonce + out.write("<a href=\"" + uri + "?action=StopAll&nonce=" + _nonce +
"\" title=\"Stop all torrents and the i2p tunnel\">Stop All</a>"); "\" title=\"Stop all torrents and the i2p tunnel\">Stop All</a>");
else if (snarks.size() > 0) else if (snarks.size() > 0)
@ -330,7 +330,7 @@ public class I2PSnarkServlet extends HttpServlet {
_manager.addMessage("Error creating torrent - you must select a tracker"); _manager.addMessage("Error creating torrent - you must select a tracker");
else if (baseFile.exists()) { else if (baseFile.exists()) {
try { try {
Storage s = new Storage(baseFile, announceURL, null); Storage s = new Storage(_manager.util(), baseFile, announceURL, null);
s.create(); s.create();
s.close(); // close the files... maybe need a way to pass this Storage to addTorrent rather than starting over s.close(); // close the files... maybe need a way to pass this Storage to addTorrent rather than starting over
MetaInfo info = s.getMetaInfo(); MetaInfo info = s.getMetaInfo();
@ -361,8 +361,8 @@ public class I2PSnarkServlet extends HttpServlet {
if (!snark.stopped) if (!snark.stopped)
_manager.stopTorrent(snark.torrent, false); _manager.stopTorrent(snark.torrent, false);
} }
if (I2PSnarkUtil.instance().connected()) { if (_manager.util().connected()) {
I2PSnarkUtil.instance().disconnect(); _manager.util().disconnect();
_manager.addMessage("I2P tunnel closed"); _manager.addMessage("I2P tunnel closed");
} }
} else if ("StartAll".equals(action)) { } else if ("StartAll".equals(action)) {
@ -690,8 +690,8 @@ public class I2PSnarkServlet extends HttpServlet {
String uri = req.getRequestURI(); String uri = req.getRequestURI();
String dataDir = _manager.getDataDir().getAbsolutePath(); String dataDir = _manager.getDataDir().getAbsolutePath();
boolean autoStart = _manager.shouldAutoStart(); boolean autoStart = _manager.shouldAutoStart();
boolean useOpenTrackers = I2PSnarkUtil.instance().shouldUseOpenTrackers(); boolean useOpenTrackers = _manager.util().shouldUseOpenTrackers();
String openTrackers = I2PSnarkUtil.instance().getOpenTrackerString(); String openTrackers = _manager.util().getOpenTrackerString();
//int seedPct = 0; //int seedPct = 0;
out.write("<form action=\"" + uri + "\" method=\"POST\">\n"); out.write("<form action=\"" + uri + "\" method=\"POST\">\n");
@ -723,9 +723,9 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("</select><br />\n"); out.write("</select><br />\n");
*/ */
out.write("Total uploader limit: <input type=\"text\" name=\"upLimit\" value=\"" 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=\"" 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\" " out.write("Use open trackers also: <input type=\"checkbox\" name=\"useOpenTrackers\" value=\"true\" "
+ (useOpenTrackers ? "checked " : "") + (useOpenTrackers ? "checked " : "")
@ -735,15 +735,15 @@ public class I2PSnarkServlet extends HttpServlet {
//out.write("<hr />\n"); //out.write("<hr />\n");
out.write("EepProxy host: <input type=\"text\" name=\"eepHost\" value=\"" 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=\"" 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=\"" 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=\"" + 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); 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(); ) { for (Iterator iter = options.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry entry = (Map.Entry)iter.next(); Map.Entry entry = (Map.Entry)iter.next();
String key = (String)entry.getKey(); String key = (String)entry.getKey();
@ -877,7 +877,7 @@ class FetchAndAdd implements Runnable {
public void run() { public void run() {
_url = _url.trim(); _url = _url.trim();
// 3 retries // 3 retries
File file = I2PSnarkUtil.instance().get(_url, false, 3); File file = _manager.util().get(_url, false, 3);
try { try {
if ( (file != null) && (file.exists()) && (file.length() > 0) ) { if ( (file != null) && (file.exists()) && (file.length() > 0) ) {
_manager.addMessage("Torrent fetched from " + _url); _manager.addMessage("Torrent fetched from " + _url);