forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p' (head 9ca94e960929c6af5dea1085105278d2f33217f2)
to branch 'i2p.i2p.zzz.dhtsnark' (head 1f23a71b0fa5169c220f3f21dd705e1fcfbb1b5d)
This commit is contained in:
@ -325,7 +325,10 @@ abstract class ExtensionHandler {
|
||||
BDecoder dec = new BDecoder(is);
|
||||
BEValue bev = dec.bdecodeMap();
|
||||
Map<String, BEValue> map = bev.getMap();
|
||||
byte[] ids = map.get("added").getBytes();
|
||||
bev = map.get("added");
|
||||
if (bev == null)
|
||||
return;
|
||||
byte[] ids = bev.getBytes();
|
||||
if (ids.length < HASH_LENGTH)
|
||||
return;
|
||||
int len = Math.min(ids.length, (I2PSnarkUtil.MAX_CONNECTIONS - 1) * HASH_LENGTH);
|
||||
|
@ -55,8 +55,9 @@ public class I2PSnarkUtil {
|
||||
private String _i2cpHost;
|
||||
private int _i2cpPort;
|
||||
private final Map<String, String> _opts;
|
||||
private I2PSocketManager _manager;
|
||||
private volatile I2PSocketManager _manager;
|
||||
private boolean _configured;
|
||||
private volatile boolean _connecting;
|
||||
private final Set<Hash> _shitlist;
|
||||
private int _maxUploaders;
|
||||
private int _maxUpBW;
|
||||
@ -200,6 +201,7 @@ public class I2PSnarkUtil {
|
||||
*/
|
||||
synchronized public boolean connect() {
|
||||
if (_manager == null) {
|
||||
_connecting = true;
|
||||
// try to find why reconnecting after stop
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Connecting to I2P", new Exception("I did it"));
|
||||
@ -239,6 +241,7 @@ public class I2PSnarkUtil {
|
||||
if (opts.getProperty("i2p.streaming.maxConnsPerHour") == null)
|
||||
opts.setProperty("i2p.streaming.maxConnsPerHour", "20");
|
||||
_manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
|
||||
_connecting = false;
|
||||
}
|
||||
// FIXME this only instantiates krpc once, left stuck with old manager
|
||||
if (_shouldUseDHT && _manager != null && _dht == null)
|
||||
@ -254,6 +257,9 @@ public class I2PSnarkUtil {
|
||||
|
||||
public boolean connected() { return _manager != null; }
|
||||
|
||||
/** @since 0.9.1 */
|
||||
public boolean isConnecting() { return _manager == null && _connecting; }
|
||||
|
||||
/**
|
||||
* For FetchAndAdd
|
||||
* @return null if not connected
|
||||
@ -275,8 +281,11 @@ public class I2PSnarkUtil {
|
||||
// FIXME this can cause race NPEs elsewhere
|
||||
_manager = null;
|
||||
_shitlist.clear();
|
||||
if (mgr != null)
|
||||
if (mgr != null) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Disconnecting from I2P", new Exception("I did it"));
|
||||
mgr.destroySocketManager();
|
||||
}
|
||||
// this will delete a .torrent file d/l in progress so don't do that...
|
||||
FileUtil.rmdir(_tmpDir, false);
|
||||
// in case the user will d/l a .torrent file next...
|
||||
|
@ -39,13 +39,13 @@ class PeerState implements DataLoader
|
||||
|
||||
// Interesting and choking describes whether we are interested in or
|
||||
// are choking the other side.
|
||||
boolean interesting = false;
|
||||
boolean choking = true;
|
||||
volatile boolean interesting;
|
||||
volatile boolean choking = true;
|
||||
|
||||
// Interested and choked describes whether the other side is
|
||||
// interested in us or choked us.
|
||||
boolean interested = false;
|
||||
boolean choked = true;
|
||||
volatile boolean interested;
|
||||
volatile boolean choked = true;
|
||||
|
||||
/** the pieces the peer has */
|
||||
BitField bitfield;
|
||||
|
@ -250,6 +250,7 @@ public class Snark
|
||||
private String rootDataDir = ".";
|
||||
private final CompleteListener completeListener;
|
||||
private boolean stopped;
|
||||
private boolean starting;
|
||||
private byte[] id;
|
||||
private byte[] infoHash;
|
||||
private String additionalTrackerURL;
|
||||
@ -509,9 +510,19 @@ public class Snark
|
||||
}
|
||||
|
||||
/**
|
||||
* Start up contacting peers and querying the tracker
|
||||
* Start up contacting peers and querying the tracker.
|
||||
* Blocks if tunnel is not yet open.
|
||||
*/
|
||||
public void startTorrent() {
|
||||
public synchronized void startTorrent() {
|
||||
starting = true;
|
||||
try {
|
||||
x_startTorrent();
|
||||
} finally {
|
||||
starting = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void x_startTorrent() {
|
||||
boolean ok = _util.connect();
|
||||
if (!ok) fatal("Unable to connect to I2P");
|
||||
if (coordinator == null) {
|
||||
@ -572,14 +583,24 @@ public class Snark
|
||||
debug("NOT starting TrackerClient???", NOTICE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop contacting the tracker and talking with peers
|
||||
*/
|
||||
public void stopTorrent() {
|
||||
stopTorrent(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop contacting the tracker and talking with peers
|
||||
* @param fast if true, limit the life of the unannounce threads
|
||||
* @since 0.9.1
|
||||
*/
|
||||
public synchronized void stopTorrent(boolean fast) {
|
||||
stopped = true;
|
||||
TrackerClient tc = trackerclient;
|
||||
if (tc != null)
|
||||
tc.halt();
|
||||
tc.halt(fast);
|
||||
PeerCoordinator pc = coordinator;
|
||||
if (pc != null)
|
||||
pc.halt();
|
||||
@ -670,6 +691,22 @@ public class Snark
|
||||
return stopped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Startup in progress.
|
||||
* @since 0.9.1
|
||||
*/
|
||||
public boolean isStarting() {
|
||||
return starting && stopped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set startup in progress.
|
||||
* @since 0.9.1
|
||||
*/
|
||||
public void setStarting() {
|
||||
starting = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 0.8.4
|
||||
*/
|
||||
|
@ -34,6 +34,8 @@ import net.i2p.util.Log;
|
||||
import net.i2p.util.OrderedProperties;
|
||||
import net.i2p.util.SecureDirectory;
|
||||
import net.i2p.util.SecureFileOutputStream;
|
||||
import net.i2p.util.SimpleScheduler;
|
||||
import net.i2p.util.SimpleTimer;
|
||||
|
||||
/**
|
||||
* Manage multiple snarks
|
||||
@ -59,6 +61,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
private ConnectionAcceptor _connectionAcceptor;
|
||||
private Thread _monitor;
|
||||
private volatile boolean _running;
|
||||
private volatile boolean _stopping;
|
||||
private final Map<String, Tracker> _trackerMap;
|
||||
|
||||
public static final String PROP_I2CP_HOST = "i2psnark.i2cpHost";
|
||||
@ -146,16 +149,26 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
_connectionAcceptor = new ConnectionAcceptor(_util);
|
||||
_monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor", true);
|
||||
_monitor.start();
|
||||
_context.addShutdownTask(new SnarkManagerShutdown());
|
||||
// Not required, Jetty has a shutdown hook
|
||||
//_context.addShutdownTask(new SnarkManagerShutdown());
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by the webapp at Jetty shutdown.
|
||||
* Stops all torrents. Does not close the tunnel, so the announces have a chance.
|
||||
* Fix this so an individual webaapp stop will close the tunnel.
|
||||
* Runs inline.
|
||||
*/
|
||||
public void stop() {
|
||||
_running = false;
|
||||
_monitor.interrupt();
|
||||
_connectionAcceptor.halt();
|
||||
(new SnarkManagerShutdown()).run();
|
||||
stopAllTorrents(true);
|
||||
}
|
||||
|
||||
/** @since 0.9.1 */
|
||||
public boolean isStopping() { return _stopping; }
|
||||
|
||||
/** hook to I2PSnarkUtil for the servlet */
|
||||
public I2PSnarkUtil util() { return _util; }
|
||||
|
||||
@ -871,7 +884,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
torrent.startTorrent();
|
||||
addMessage(_("Fetching {0}", name));
|
||||
boolean haveSavedPeers = false;
|
||||
if ((!util().connected()) && !haveSavedPeers) {
|
||||
if ((_util.connected()) && !haveSavedPeers) {
|
||||
addMessage(_("We have no saved peers and no other torrents are running. " +
|
||||
"Fetch of {0} will not succeed until you start another torrent.", name));
|
||||
}
|
||||
@ -1603,21 +1616,137 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
}
|
||||
}
|
||||
|
||||
private class SnarkManagerShutdown extends I2PAppThread {
|
||||
@Override
|
||||
public void run() {
|
||||
Set names = listTorrentFiles();
|
||||
int running = 0;
|
||||
for (Iterator iter = names.iterator(); iter.hasNext(); ) {
|
||||
Snark snark = getTorrent((String)iter.next());
|
||||
if (snark != null && !snark.isStopped()) {
|
||||
snark.stopTorrent();
|
||||
try { Thread.sleep(50); } catch (InterruptedException ie) {}
|
||||
/**
|
||||
* If not connected, thread it, otherwise inline
|
||||
* @since 0.9.1
|
||||
*/
|
||||
public void startTorrent(byte[] infoHash) {
|
||||
for (Snark snark : _snarks.values()) {
|
||||
if (DataHelper.eq(infoHash, snark.getInfoHash())) {
|
||||
if (snark.isStarting() || !snark.isStopped()) {
|
||||
addMessage("Torrent already started");
|
||||
return;
|
||||
}
|
||||
boolean connected = _util.connected();
|
||||
if ((!connected) && !_util.isConnecting())
|
||||
addMessage(_("Opening the I2P tunnel"));
|
||||
addMessage(_("Starting up torrent {0}", snark.getBaseName()));
|
||||
if (connected) {
|
||||
snark.startTorrent();
|
||||
} else {
|
||||
// mark it for the UI
|
||||
snark.setStarting();
|
||||
(new I2PAppThread(new ThreadedStarter(snark), "TorrentStarter", true)).start();
|
||||
try { Thread.sleep(200); } catch (InterruptedException ie) {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
addMessage("Torrent not found?");
|
||||
}
|
||||
|
||||
/**
|
||||
* If not connected, thread it, otherwise inline
|
||||
* @since 0.9.1
|
||||
*/
|
||||
public void startAllTorrents() {
|
||||
if (_util.connected()) {
|
||||
startAll();
|
||||
} else {
|
||||
addMessage(_("Opening the I2P tunnel and starting all torrents."));
|
||||
for (Snark snark : _snarks.values()) {
|
||||
// mark it for the UI
|
||||
snark.setStarting();
|
||||
}
|
||||
(new I2PAppThread(new ThreadedStarter(null), "TorrentStarterAll", true)).start();
|
||||
try { Thread.sleep(200); } catch (InterruptedException ie) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use null constructor param for all
|
||||
* @since 0.9.1
|
||||
*/
|
||||
private class ThreadedStarter implements Runnable {
|
||||
private final Snark snark;
|
||||
public ThreadedStarter(Snark s) { snark = s; }
|
||||
public void run() {
|
||||
if (snark != null) {
|
||||
if (snark.isStopped())
|
||||
snark.startTorrent();
|
||||
} else {
|
||||
startAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inline
|
||||
* @since 0.9.1
|
||||
*/
|
||||
private void startAll() {
|
||||
for (Snark snark : _snarks.values()) {
|
||||
if (snark.isStopped())
|
||||
snark.startTorrent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop all running torrents, and close the tunnel after a delay
|
||||
* to allow for announces.
|
||||
* If called at router shutdown via Jetty shutdown hook -> webapp destroy() -> stop(),
|
||||
* the tunnel won't actually be closed as the SimpleScheduler is already shutdown
|
||||
* or will be soon, so we delay a few seconds inline.
|
||||
* @param finalShutdown if true, sleep at the end if any torrents were running
|
||||
* @since 0.9.1
|
||||
*/
|
||||
public void stopAllTorrents(boolean finalShutdown) {
|
||||
_stopping = true;
|
||||
if (finalShutdown && _log.shouldLog(Log.WARN))
|
||||
_log.warn("SnarkManager final shutdown");
|
||||
int count = 0;
|
||||
for (Snark snark : _snarks.values()) {
|
||||
if (!snark.isStopped()) {
|
||||
if (count == 0)
|
||||
addMessage(_("Stopping all torrents and closing the I2P tunnel."));
|
||||
count++;
|
||||
if (finalShutdown)
|
||||
snark.stopTorrent(true);
|
||||
else
|
||||
stopTorrent(snark, false);
|
||||
// Throttle since every unannounce is now threaded.
|
||||
// How to do this without creating a ton of threads?
|
||||
try { Thread.sleep(20); } catch (InterruptedException ie) {}
|
||||
}
|
||||
}
|
||||
if (_util.connected()) {
|
||||
if (count > 0) {
|
||||
// Schedule this even for final shutdown, as there's a chance
|
||||
// that it's just this webapp that is stopping.
|
||||
SimpleScheduler.getInstance().addEvent(new Disconnector(), 60*1000);
|
||||
addMessage(_("Closing I2P tunnel after notifying trackers."));
|
||||
if (finalShutdown) {
|
||||
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
|
||||
}
|
||||
} else {
|
||||
_util.disconnect();
|
||||
_stopping = false;
|
||||
addMessage(_("I2P tunnel closed."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 0.9.1 */
|
||||
private class Disconnector implements SimpleTimer.TimedEvent {
|
||||
public void timeReached() {
|
||||
if (_util.connected()) {
|
||||
_util.disconnect();
|
||||
_stopping = false;
|
||||
addMessage(_("I2P tunnel closed."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ignore case, current locale
|
||||
* @since 0.9
|
||||
|
@ -26,6 +26,7 @@ import net.i2p.util.I2PAppThread;
|
||||
|
||||
/**
|
||||
* Makes sure everything ends correctly when shutting down.
|
||||
* @deprecated unused
|
||||
*/
|
||||
public class SnarkShutdown extends I2PAppThread
|
||||
{
|
||||
@ -61,7 +62,7 @@ public class SnarkShutdown extends I2PAppThread
|
||||
|
||||
//Snark.debug("Halting TrackerClient...", Snark.INFO);
|
||||
if (trackerclient != null)
|
||||
trackerclient.halt();
|
||||
trackerclient.halt(true);
|
||||
|
||||
//Snark.debug("Halting PeerCoordinator...", Snark.INFO);
|
||||
if (coordinator != null)
|
||||
|
@ -28,6 +28,7 @@ import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -97,6 +98,7 @@ public class TrackerClient implements Runnable {
|
||||
// these 2 used in loop()
|
||||
private volatile boolean runStarted;
|
||||
private volatile int consecutiveFails;
|
||||
private volatile boolean _fastUnannounce;
|
||||
|
||||
private final List<Tracker> trackers;
|
||||
|
||||
@ -134,6 +136,7 @@ public class TrackerClient implements Runnable {
|
||||
stop = false;
|
||||
consecutiveFails = 0;
|
||||
runStarted = false;
|
||||
_fastUnannounce = false;
|
||||
_thread = new I2PAppThread(this, _threadName + " #" + (++_runCount), true);
|
||||
_thread.start();
|
||||
started = true;
|
||||
@ -144,8 +147,9 @@ public class TrackerClient implements Runnable {
|
||||
|
||||
/**
|
||||
* Interrupts this Thread to stop it.
|
||||
* @param fast if true, limit the life of the unannounce threads
|
||||
*/
|
||||
public synchronized void halt() {
|
||||
public synchronized void halt(boolean fast) {
|
||||
boolean wasStopped = stop;
|
||||
if (wasStopped) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
@ -168,6 +172,7 @@ public class TrackerClient implements Runnable {
|
||||
_log.debug("Interrupting " + t.getName());
|
||||
t.interrupt();
|
||||
}
|
||||
_fastUnannounce = true;
|
||||
if (!wasStopped)
|
||||
unannounce();
|
||||
}
|
||||
@ -236,7 +241,7 @@ public class TrackerClient implements Runnable {
|
||||
* Do this one time only (not every time it is started).
|
||||
* @since 0.9.1
|
||||
*/
|
||||
public void setup() {
|
||||
private void setup() {
|
||||
// Construct the list of trackers for this torrent,
|
||||
// starting with the primary one listed in the metainfo,
|
||||
// followed by the secondary open trackers
|
||||
@ -415,6 +420,9 @@ public class TrackerClient implements Runnable {
|
||||
tr.interval = LONG_SLEEP; // slow down
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_util.debug("Not announcing to " + tr.announce + " last announce was " +
|
||||
new Date(tr.lastRequestTime) + " interval is " + DataHelper.formatDuration(tr.interval), Snark.INFO);
|
||||
}
|
||||
if ((!tr.stop) && maxSeenPeers < tr.seenPeers)
|
||||
maxSeenPeers = tr.seenPeers;
|
||||
@ -439,6 +447,8 @@ public class TrackerClient implements Runnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_util.debug("Not getting PEX peers", Snark.INFO);
|
||||
}
|
||||
|
||||
// Get peers from DHT
|
||||
@ -476,6 +486,8 @@ public class TrackerClient implements Runnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_util.debug("Not getting DHT peers", Snark.INFO);
|
||||
}
|
||||
|
||||
|
||||
@ -534,7 +546,7 @@ public class TrackerClient implements Runnable {
|
||||
if (_util.connected() &&
|
||||
tr.started && (!tr.stop) && tr.trackerProblems == null) {
|
||||
try {
|
||||
(new I2PAppThread(new Unannouncer(tr), _threadName + " Unannounce " + (++i), true)).start();
|
||||
(new I2PAppThread(new Unannouncer(tr), _threadName + " U" + (++i), true)).start();
|
||||
} catch (OutOfMemoryError oom) {
|
||||
// probably ran out of threads, ignore
|
||||
tr.reset();
|
||||
@ -611,8 +623,9 @@ public class TrackerClient implements Runnable {
|
||||
_util.debug("Sending TrackerClient request: " + s, Snark.INFO);
|
||||
|
||||
tr.lastRequestTime = System.currentTimeMillis();
|
||||
// Don't wait for a response to stopped.
|
||||
File fetched = _util.get(s, true, event.equals(STOPPED_EVENT) ? -1 : 0);
|
||||
// Don't wait for a response to stopped when shutting down
|
||||
boolean fast = _fastUnannounce && event.equals(STOPPED_EVENT);
|
||||
File fetched = _util.get(s, true, fast ? -1 : 0);
|
||||
if (fetched == null) {
|
||||
throw new IOException("Error fetching " + s);
|
||||
}
|
||||
@ -671,7 +684,7 @@ public class TrackerClient implements Runnable {
|
||||
* @return true for i2p hosts only
|
||||
* @since 0.7.12
|
||||
*/
|
||||
static boolean isValidAnnounce(String ann) {
|
||||
public static boolean isValidAnnounce(String ann) {
|
||||
URL url;
|
||||
try {
|
||||
url = new URL(ann);
|
||||
|
@ -74,6 +74,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
_context = I2PAppContext.getGlobalContext();
|
||||
_log = _context.logManager().getLog(I2PSnarkServlet.class);
|
||||
_nonce = _context.random().nextLong();
|
||||
// FIXME instantiate new one every time
|
||||
_manager = SnarkManager.instance();
|
||||
String configFile = _context.getProperty(PROP_CONFIG_FILE);
|
||||
if ( (configFile == null) || (configFile.trim().length() <= 0) )
|
||||
@ -322,7 +323,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
final long stats[] = {0,0,0,0,0,0};
|
||||
String peerParam = req.getParameter("p");
|
||||
|
||||
List snarks = getSortedSnarks(req);
|
||||
List<Snark> snarks = getSortedSnarks(req);
|
||||
boolean isForm = _manager.util().connected() || !snarks.isEmpty();
|
||||
if (isForm) {
|
||||
out.write("<form action=\"_post\" method=\"POST\">\n");
|
||||
@ -407,7 +408,9 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
ua.startsWith("Dillo"));
|
||||
|
||||
boolean noThinsp = isDegraded || (ua != null && ua.startsWith("Opera"));
|
||||
if (_manager.util().connected()) {
|
||||
if (_manager.isStopping()) {
|
||||
out.write(" ");
|
||||
} else if (_manager.util().connected()) {
|
||||
if (isDegraded)
|
||||
out.write("<a href=\"/i2psnark/?action=StopAll&nonce=" + _nonce + "\"><img title=\"");
|
||||
else {
|
||||
@ -421,7 +424,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
out.write("\">");
|
||||
if (isDegraded)
|
||||
out.write("</a>");
|
||||
} else if (!snarks.isEmpty()) {
|
||||
} else if ((!_manager.util().isConnecting()) && !snarks.isEmpty()) {
|
||||
if (isDegraded)
|
||||
out.write("<a href=\"/i2psnark/?action=StartAll&nonce=" + _nonce + "\"><img title=\"");
|
||||
else
|
||||
@ -572,14 +575,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
if (torrent != null) {
|
||||
byte infoHash[] = Base64.decode(torrent);
|
||||
if ( (infoHash != null) && (infoHash.length == 20) ) { // valid sha1
|
||||
for (String name : _manager.listTorrentFiles()) {
|
||||
Snark snark = _manager.getTorrent(name);
|
||||
if ( (snark != null) && (DataHelper.eq(infoHash, snark.getInfoHash())) ) {
|
||||
snark.startTorrent();
|
||||
_manager.addMessage(_("Starting up torrent {0}", snark.getBaseName()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
_manager.startTorrent(infoHash);
|
||||
}
|
||||
}
|
||||
} else if (action.startsWith("Remove_")) {
|
||||
@ -644,10 +640,11 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
// multifile torrents have the getFiles() return lists of lists of filenames, but
|
||||
// each of those lists just contain a single file afaict...
|
||||
File df = Storage.getFileFromNames(f, files.get(i));
|
||||
if (df.delete())
|
||||
_manager.addMessage(_("Data file deleted: {0}", df.getAbsolutePath()));
|
||||
else
|
||||
if (df.delete()) {
|
||||
//_manager.addMessage(_("Data file deleted: {0}", df.getAbsolutePath()));
|
||||
} else {
|
||||
_manager.addMessage(_("Data file could not be deleted: {0}", df.getAbsolutePath()));
|
||||
}
|
||||
}
|
||||
// step 2 make Set of dirs with reverse sort
|
||||
Set<File> dirs = new TreeSet(Collections.reverseOrder());
|
||||
@ -659,16 +656,20 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
// step 3 delete dirs bottom-up
|
||||
for (File df : dirs) {
|
||||
if (df.delete()) {
|
||||
_manager.addMessage(_("Data dir deleted: {0}", df.getAbsolutePath()));
|
||||
} else if (_log.shouldLog(Log.WARN)) {
|
||||
_log.warn("Could not delete dir " + df);
|
||||
//_manager.addMessage(_("Data dir deleted: {0}", df.getAbsolutePath()));
|
||||
} else {
|
||||
_manager.addMessage(_("Directory could not be deleted: {0}", df.getAbsolutePath()));
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Could not delete dir " + df);
|
||||
}
|
||||
}
|
||||
// step 4 delete base
|
||||
if (f.delete()) {
|
||||
_manager.addMessage(_("Data dir deleted: {0}", f.getAbsolutePath()));
|
||||
} else if (_log.shouldLog(Log.WARN)) {
|
||||
_log.warn("Could not delete dir " + f);
|
||||
_manager.addMessage(_("Directory deleted: {0}", f.getAbsolutePath()));
|
||||
} else {
|
||||
_manager.addMessage(_("Directory could not be deleted: {0}", f.getAbsolutePath()));
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Could not delete dir " + f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -740,29 +741,9 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
_manager.addMessage(_("Error creating torrent - you must enter a file or directory"));
|
||||
}
|
||||
} else if ("StopAll".equals(action)) {
|
||||
_manager.addMessage(_("Stopping all torrents and closing the I2P tunnel."));
|
||||
List snarks = getSortedSnarks(req);
|
||||
for (int i = 0; i < snarks.size(); i++) {
|
||||
Snark snark = (Snark)snarks.get(i);
|
||||
if (!snark.isStopped()) {
|
||||
_manager.stopTorrent(snark, false);
|
||||
try { Thread.sleep(50); } catch (InterruptedException ie) {}
|
||||
}
|
||||
}
|
||||
if (_manager.util().connected()) {
|
||||
// Give the stopped announces time to get out
|
||||
try { Thread.sleep(2000); } catch (InterruptedException ie) {}
|
||||
_manager.util().disconnect();
|
||||
_manager.addMessage(_("I2P tunnel closed."));
|
||||
}
|
||||
_manager.stopAllTorrents(false);
|
||||
} else if ("StartAll".equals(action)) {
|
||||
_manager.addMessage(_("Opening the I2P tunnel and starting all torrents."));
|
||||
List snarks = getSortedSnarks(req);
|
||||
for (int i = 0; i < snarks.size(); i++) {
|
||||
Snark snark = (Snark)snarks.get(i);
|
||||
if (snark.isStopped())
|
||||
snark.startTorrent();
|
||||
}
|
||||
_manager.startAllTorrents();
|
||||
} else if ("Clear".equals(action)) {
|
||||
_manager.clearMessages();
|
||||
} else {
|
||||
@ -826,7 +807,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
name = name.trim();
|
||||
hurl = hurl.trim();
|
||||
aurl = aurl.trim().replace("=", "=");
|
||||
if (name.length() > 0 && hurl.startsWith("http://") && aurl.startsWith("http://")) {
|
||||
if (name.length() > 0 && hurl.startsWith("http://") && TrackerClient.isValidAnnounce(aurl)) {
|
||||
Map<String, Tracker> trackers = _manager.getTrackerMap();
|
||||
trackers.put(name, new Tracker(name, aurl, hurl));
|
||||
_manager.saveTrackerMap();
|
||||
@ -998,6 +979,8 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
|
||||
"<br>" + err;
|
||||
}
|
||||
} else if (snark.isStarting()) {
|
||||
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Starting");
|
||||
} else if (remaining == 0 || needed == 0) { // < 0 means no meta size yet
|
||||
// partial complete or seeding
|
||||
if (isRunning) {
|
||||
@ -1150,6 +1133,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
if (showPeers)
|
||||
parameters = parameters + "&p=1";
|
||||
if (isRunning) {
|
||||
// Stop Button
|
||||
if (isDegraded)
|
||||
out.write("<a href=\"/i2psnark/?action=Stop_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
||||
else
|
||||
@ -1160,7 +1144,9 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
out.write("\">");
|
||||
if (isDegraded)
|
||||
out.write("</a>");
|
||||
} else {
|
||||
} else if (!snark.isStarting()) {
|
||||
if (!_manager.isStopping()) {
|
||||
// Start Button
|
||||
// This works in Opera but it's displayed a little differently, so use noThinsp here too so all 3 icons are consistent
|
||||
if (noThinsp)
|
||||
out.write("<a href=\"/i2psnark/?action=Start_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
||||
@ -1172,8 +1158,9 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
out.write("\">");
|
||||
if (isDegraded)
|
||||
out.write("</a>");
|
||||
|
||||
}
|
||||
if (isValid) {
|
||||
// Remove Button
|
||||
// Doesnt work with Opera so use noThinsp instead of isDegraded
|
||||
if (noThinsp)
|
||||
out.write("<a href=\"/i2psnark/?action=Remove_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
||||
@ -1193,6 +1180,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
out.write("</a>");
|
||||
}
|
||||
|
||||
// Delete Button
|
||||
// Doesnt work with Opera so use noThinsp instead of isDegraded
|
||||
if (noThinsp)
|
||||
out.write("<a href=\"/i2psnark/?action=Delete_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
||||
|
Reference in New Issue
Block a user