forked from I2P_Developers/i2p.i2p
- Thread task to open tunnel and improve UI feedback while open is pending
This commit is contained in:
@ -55,8 +55,9 @@ public class I2PSnarkUtil {
|
|||||||
private String _i2cpHost;
|
private String _i2cpHost;
|
||||||
private int _i2cpPort;
|
private int _i2cpPort;
|
||||||
private final Map<String, String> _opts;
|
private final Map<String, String> _opts;
|
||||||
private I2PSocketManager _manager;
|
private volatile I2PSocketManager _manager;
|
||||||
private boolean _configured;
|
private boolean _configured;
|
||||||
|
private volatile boolean _connecting;
|
||||||
private final Set<Hash> _shitlist;
|
private final Set<Hash> _shitlist;
|
||||||
private int _maxUploaders;
|
private int _maxUploaders;
|
||||||
private int _maxUpBW;
|
private int _maxUpBW;
|
||||||
@ -198,6 +199,7 @@ public class I2PSnarkUtil {
|
|||||||
*/
|
*/
|
||||||
synchronized public boolean connect() {
|
synchronized public boolean connect() {
|
||||||
if (_manager == null) {
|
if (_manager == null) {
|
||||||
|
_connecting = true;
|
||||||
// try to find why reconnecting after stop
|
// try to find why reconnecting after stop
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Connecting to I2P", new Exception("I did it"));
|
_log.debug("Connecting to I2P", new Exception("I did it"));
|
||||||
@ -237,6 +239,7 @@ public class I2PSnarkUtil {
|
|||||||
if (opts.getProperty("i2p.streaming.maxConnsPerHour") == null)
|
if (opts.getProperty("i2p.streaming.maxConnsPerHour") == null)
|
||||||
opts.setProperty("i2p.streaming.maxConnsPerHour", "20");
|
opts.setProperty("i2p.streaming.maxConnsPerHour", "20");
|
||||||
_manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
|
_manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
|
||||||
|
_connecting = false;
|
||||||
}
|
}
|
||||||
// FIXME this only instantiates krpc once, left stuck with old manager
|
// FIXME this only instantiates krpc once, left stuck with old manager
|
||||||
//if (ENABLE_DHT && _manager != null && _dht == null)
|
//if (ENABLE_DHT && _manager != null && _dht == null)
|
||||||
@ -252,6 +255,9 @@ public class I2PSnarkUtil {
|
|||||||
|
|
||||||
public boolean connected() { return _manager != null; }
|
public boolean connected() { return _manager != null; }
|
||||||
|
|
||||||
|
/** @since 0.9.1 */
|
||||||
|
public boolean isConnecting() { return _manager == null && _connecting; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For FetchAndAdd
|
* For FetchAndAdd
|
||||||
* @return null if not connected
|
* @return null if not connected
|
||||||
|
@ -250,6 +250,7 @@ public class Snark
|
|||||||
private String rootDataDir = ".";
|
private String rootDataDir = ".";
|
||||||
private final CompleteListener completeListener;
|
private final CompleteListener completeListener;
|
||||||
private boolean stopped;
|
private boolean stopped;
|
||||||
|
private boolean starting;
|
||||||
private byte[] id;
|
private byte[] id;
|
||||||
private byte[] infoHash;
|
private byte[] infoHash;
|
||||||
private String additionalTrackerURL;
|
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();
|
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) {
|
||||||
@ -585,7 +596,7 @@ public class Snark
|
|||||||
* @param fast if true, limit the life of the unannounce threads
|
* @param fast if true, limit the life of the unannounce threads
|
||||||
* @since 0.9.1
|
* @since 0.9.1
|
||||||
*/
|
*/
|
||||||
public void stopTorrent(boolean fast) {
|
public synchronized void stopTorrent(boolean fast) {
|
||||||
stopped = true;
|
stopped = true;
|
||||||
TrackerClient tc = trackerclient;
|
TrackerClient tc = trackerclient;
|
||||||
if (tc != null)
|
if (tc != null)
|
||||||
@ -680,6 +691,22 @@ public class Snark
|
|||||||
return stopped;
|
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
|
* @since 0.8.4
|
||||||
*/
|
*/
|
||||||
|
@ -867,7 +867,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
torrent.startTorrent();
|
torrent.startTorrent();
|
||||||
addMessage(_("Fetching {0}", name));
|
addMessage(_("Fetching {0}", name));
|
||||||
boolean haveSavedPeers = false;
|
boolean haveSavedPeers = false;
|
||||||
if ((!util().connected()) && !haveSavedPeers) {
|
if ((_util.connected()) && !haveSavedPeers) {
|
||||||
addMessage(_("We have no saved peers and no other torrents are running. " +
|
addMessage(_("We have no saved peers and no other torrents are running. " +
|
||||||
"Fetch of {0} will not succeed until you start another torrent.", name));
|
"Fetch of {0} will not succeed until you start another torrent.", name));
|
||||||
}
|
}
|
||||||
@ -1599,6 +1599,81 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* Stop all running torrents, and close the tunnel after a delay
|
||||||
* to allow for announces.
|
* to allow for announces.
|
||||||
@ -1631,7 +1706,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
// Schedule this even for final shutdown, as there's a chance
|
// Schedule this even for final shutdown, as there's a chance
|
||||||
// that it's just this webapp that is stopping.
|
// that it's just this webapp that is stopping.
|
||||||
SimpleScheduler.getInstance().addEvent(new Disconnector(), 60*1000);
|
SimpleScheduler.getInstance().addEvent(new Disconnector(), 60*1000);
|
||||||
addMessage(_("Closing I2P tunnel after announces to trackers."));
|
addMessage(_("Closing I2P tunnel after notifying trackers."));
|
||||||
if (finalShutdown) {
|
if (finalShutdown) {
|
||||||
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
|
try { Thread.sleep(5*1000); } catch (InterruptedException ie) {}
|
||||||
}
|
}
|
||||||
|
@ -422,7 +422,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
out.write("\">");
|
out.write("\">");
|
||||||
if (isDegraded)
|
if (isDegraded)
|
||||||
out.write("</a>");
|
out.write("</a>");
|
||||||
} else if (!snarks.isEmpty()) {
|
} else if ((!_manager.util().isConnecting()) && !snarks.isEmpty()) {
|
||||||
if (isDegraded)
|
if (isDegraded)
|
||||||
out.write("<a href=\"/i2psnark/?action=StartAll&nonce=" + _nonce + "\"><img title=\"");
|
out.write("<a href=\"/i2psnark/?action=StartAll&nonce=" + _nonce + "\"><img title=\"");
|
||||||
else
|
else
|
||||||
@ -573,14 +573,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
if (torrent != null) {
|
if (torrent != null) {
|
||||||
byte infoHash[] = Base64.decode(torrent);
|
byte infoHash[] = Base64.decode(torrent);
|
||||||
if ( (infoHash != null) && (infoHash.length == 20) ) { // valid sha1
|
if ( (infoHash != null) && (infoHash.length == 20) ) { // valid sha1
|
||||||
for (String name : _manager.listTorrentFiles()) {
|
_manager.startTorrent(infoHash);
|
||||||
Snark snark = _manager.getTorrent(name);
|
|
||||||
if ( (snark != null) && (DataHelper.eq(infoHash, snark.getInfoHash())) ) {
|
|
||||||
snark.startTorrent();
|
|
||||||
_manager.addMessage(_("Starting up torrent {0}", snark.getBaseName()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (action.startsWith("Remove_")) {
|
} else if (action.startsWith("Remove_")) {
|
||||||
@ -747,13 +740,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
} else if ("StopAll".equals(action)) {
|
} else if ("StopAll".equals(action)) {
|
||||||
_manager.stopAllTorrents(false);
|
_manager.stopAllTorrents(false);
|
||||||
} else if ("StartAll".equals(action)) {
|
} else if ("StartAll".equals(action)) {
|
||||||
_manager.addMessage(_("Opening the I2P tunnel and starting all torrents."));
|
_manager.startAllTorrents();
|
||||||
List<Snark> snarks = getSortedSnarks(req);
|
|
||||||
for (int i = 0; i < snarks.size(); i++) {
|
|
||||||
Snark snark = snarks.get(i);
|
|
||||||
if (snark.isStopped())
|
|
||||||
snark.startTorrent();
|
|
||||||
}
|
|
||||||
} else if ("Clear".equals(action)) {
|
} else if ("Clear".equals(action)) {
|
||||||
_manager.clearMessages();
|
_manager.clearMessages();
|
||||||
} else {
|
} else {
|
||||||
@ -989,6 +976,8 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
|
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
|
||||||
"<br>" + err;
|
"<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
|
} else if (remaining == 0 || needed == 0) { // < 0 means no meta size yet
|
||||||
// partial complete or seeding
|
// partial complete or seeding
|
||||||
if (isRunning) {
|
if (isRunning) {
|
||||||
@ -1141,6 +1130,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
if (showPeers)
|
if (showPeers)
|
||||||
parameters = parameters + "&p=1";
|
parameters = parameters + "&p=1";
|
||||||
if (isRunning) {
|
if (isRunning) {
|
||||||
|
// Stop Button
|
||||||
if (isDegraded)
|
if (isDegraded)
|
||||||
out.write("<a href=\"/i2psnark/?action=Stop_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
out.write("<a href=\"/i2psnark/?action=Stop_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
||||||
else
|
else
|
||||||
@ -1151,7 +1141,8 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
out.write("\">");
|
out.write("\">");
|
||||||
if (isDegraded)
|
if (isDegraded)
|
||||||
out.write("</a>");
|
out.write("</a>");
|
||||||
} else {
|
} else if (!snark.isStarting()) {
|
||||||
|
// Start Button
|
||||||
// This works in Opera but it's displayed a little differently, so use noThinsp here too so all 3 icons are consistent
|
// This works in Opera but it's displayed a little differently, so use noThinsp here too so all 3 icons are consistent
|
||||||
if (noThinsp)
|
if (noThinsp)
|
||||||
out.write("<a href=\"/i2psnark/?action=Start_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
out.write("<a href=\"/i2psnark/?action=Start_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
||||||
@ -1165,6 +1156,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
out.write("</a>");
|
out.write("</a>");
|
||||||
|
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
|
// Remove Button
|
||||||
// Doesnt work with Opera so use noThinsp instead of isDegraded
|
// Doesnt work with Opera so use noThinsp instead of isDegraded
|
||||||
if (noThinsp)
|
if (noThinsp)
|
||||||
out.write("<a href=\"/i2psnark/?action=Remove_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
out.write("<a href=\"/i2psnark/?action=Remove_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
||||||
@ -1184,6 +1176,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
out.write("</a>");
|
out.write("</a>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete Button
|
||||||
// Doesnt work with Opera so use noThinsp instead of isDegraded
|
// Doesnt work with Opera so use noThinsp instead of isDegraded
|
||||||
if (noThinsp)
|
if (noThinsp)
|
||||||
out.write("<a href=\"/i2psnark/?action=Delete_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
out.write("<a href=\"/i2psnark/?action=Delete_" + b64 + "&nonce=" + _nonce + "\"><img title=\"");
|
||||||
|
Reference in New Issue
Block a user