forked from I2P_Developers/i2p.i2p
Compare commits
9 Commits
i2p.i2p.2.
...
i2p.i2p.2.
Author | SHA1 | Date | |
---|---|---|---|
a85faada6e | |||
b0818f95ec | |||
1c070baf6d | |||
8e2ed37544 | |||
25ba8926b7 | |||
9c533b5a27 | |||
818aa6a5c5 | |||
aa681b3f98 | |||
acffbcc1d4 |
@ -789,6 +789,22 @@ public class MetaInfo
|
||||
return Collections.unmodifiableMap(infoMap);
|
||||
}
|
||||
|
||||
public String toMagnetURI() {
|
||||
String magnetURIString = "magnet:?xt=urn:btih:" + I2PSnarkUtil.toHex(calculateInfoHash());
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Created magnet URI: " + magnetURIString);
|
||||
long exactLength = getTotalLength();
|
||||
if (exactLength != 0)
|
||||
magnetURIString += "&xl=" + exactLength;
|
||||
String announce = getAnnounce();
|
||||
if (announce != null)
|
||||
magnetURIString += "&tr=" + announce;
|
||||
List<String> webSeeds = getWebSeedURLs();
|
||||
if (webSeeds != null)
|
||||
magnetURIString += "&ws=" + webSeeds.get(0);
|
||||
return magnetURIString;
|
||||
}
|
||||
|
||||
private byte[] calculateInfoHash()
|
||||
{
|
||||
Map<String, BEValue> info = createInfoMap();
|
||||
|
@ -30,8 +30,10 @@
|
||||
<pathelement location="../../jetty/jettylib/jetty-i2p.jar" />
|
||||
<pathelement location="../../systray/java/build/obj" />
|
||||
<pathelement location="../../desktopgui/build" />
|
||||
<pathelement location="../../i2psnark/java/build/i2psnark.jar" />
|
||||
<pathelement location="../../../installer/lib/wrapper/all/wrapper.jar" />
|
||||
<pathelement location="../../jrobin/java/build/jrobin.jar" />
|
||||
<pathelement location="../../../build/mstreaming.jar" />
|
||||
</classpath>
|
||||
</depend>
|
||||
</target>
|
||||
@ -66,6 +68,7 @@
|
||||
<compilerarg line="${javac.compilerargs}" />
|
||||
<classpath>
|
||||
<pathelement location="../../../core/java/build/i2p.jar" />
|
||||
<pathelement location="../../../build/mstreaming.jar" />
|
||||
<!-- gnu-getopt.jar only present for debian builds -->
|
||||
<pathelement location="../../../core/java/build/gnu-getopt.jar" />
|
||||
<pathelement location="../../../router/java/build/router.jar" />
|
||||
@ -82,6 +85,7 @@
|
||||
<pathelement location="../../jetty/jettylib/jetty-i2p.jar" />
|
||||
<pathelement location="../../systray/java/build/systray.jar" />
|
||||
<pathelement location="../../desktopgui/dist/desktopgui.jar" />
|
||||
<pathelement location="../../i2psnark/java/build/i2psnark.jar" />
|
||||
<pathelement location="../../../installer/lib/wrapper/all/wrapper.jar" />
|
||||
<pathelement location="../../jrobin/java/build/jrobin.jar" />
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
package net.i2p.router.update;
|
||||
|
||||
import static net.i2p.update.UpdateMethod.TORRENT;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collections;
|
||||
@ -42,7 +44,7 @@ class PluginUpdateHandler implements Checker, Updater {
|
||||
public UpdateTask check(UpdateType type, UpdateMethod method,
|
||||
String appName, String currentVersion, long maxTime) {
|
||||
if ((type != UpdateType.PLUGIN) ||
|
||||
method != UpdateMethod.HTTP || appName.length() <= 0)
|
||||
(method != UpdateMethod.HTTP || method != UpdateMethod.TORRENT) || appName.length() <= 0)
|
||||
return null;
|
||||
|
||||
Properties props = PluginStarter.pluginProperties(_context, appName);
|
||||
@ -58,6 +60,9 @@ class PluginUpdateHandler implements Checker, Updater {
|
||||
_log.info("Checking for updates for " + appName + ": " + xpi2pURL);
|
||||
try {
|
||||
updateSources = Collections.singletonList(new URI(xpi2pURL));
|
||||
if (method == UpdateMethod.TORRENT)
|
||||
updateSources = Collections.singletonList(new URI(xpi2pURL + ".torrent"));
|
||||
|
||||
} catch (URISyntaxException use) {}
|
||||
}
|
||||
|
||||
@ -65,8 +70,12 @@ class PluginUpdateHandler implements Checker, Updater {
|
||||
//updateStatus("<b>" + _t("Cannot check, plugin {0} is not installed", appName) + "</b>");
|
||||
return null;
|
||||
}
|
||||
|
||||
UpdateRunner update = new PluginUpdateChecker(_context, _mgr, updateSources, appName, oldVersion);
|
||||
UpdateRunner update = null;
|
||||
if (method == UpdateMethod.TORRENT) {
|
||||
update = new PluginUpdateTorrentChecker(_context, _mgr, updateSources, appName, oldVersion);
|
||||
} else {
|
||||
update = new PluginUpdateChecker(_context, _mgr, updateSources, appName, oldVersion);
|
||||
}
|
||||
return update;
|
||||
}
|
||||
|
||||
|
@ -50,12 +50,12 @@ import net.i2p.util.VersionComparator;
|
||||
*/
|
||||
class PluginUpdateRunner extends UpdateRunner {
|
||||
|
||||
private String _appName;
|
||||
private final String _appDisplayName;
|
||||
protected String _appName;
|
||||
protected final String _appDisplayName;
|
||||
private final String _oldVersion;
|
||||
private final URI _uri;
|
||||
private final String _xpi2pURL;
|
||||
private boolean _updated;
|
||||
protected final URI _uri;
|
||||
protected final String _xpi2pURL;
|
||||
protected boolean _updated;
|
||||
private String _errMsg = "";
|
||||
|
||||
private static final String XPI2P = "app.xpi2p";
|
||||
@ -199,7 +199,7 @@ class PluginUpdateRunner extends UpdateRunner {
|
||||
* @since 0.9.15
|
||||
* @return if SU3
|
||||
*/
|
||||
private static boolean isSU3File(File f) throws IOException {
|
||||
protected static boolean isSU3File(File f) throws IOException {
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
fis = new FileInputStream(f);
|
||||
@ -217,7 +217,7 @@ class PluginUpdateRunner extends UpdateRunner {
|
||||
* @since 0.9.15
|
||||
* @return success
|
||||
*/
|
||||
private void processSUD(File f, File appDir, String url) {
|
||||
protected void processSUD(File f, File appDir, String url) {
|
||||
TrustedUpdate up = new TrustedUpdate(_context);
|
||||
File to = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + ZIP);
|
||||
// extract to a zip file whether the sig is good or not, so we can get the properties file
|
||||
@ -326,7 +326,7 @@ class PluginUpdateRunner extends UpdateRunner {
|
||||
/**
|
||||
* @since 0.9.15
|
||||
*/
|
||||
private void processSU3(File f, File appDir, String url) {
|
||||
protected void processSU3(File f, File appDir, String url) {
|
||||
SU3File su3 = new SU3File(_context, f);
|
||||
File to = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + ZIP);
|
||||
String sudVersion;
|
||||
@ -373,7 +373,7 @@ class PluginUpdateRunner extends UpdateRunner {
|
||||
* @since 0.9.15
|
||||
* @return null on error
|
||||
*/
|
||||
private Properties getPluginConfig(File f, File to, String url) {
|
||||
protected Properties getPluginConfig(File f, File to, String url) {
|
||||
File tempDir = new File(_context.getTempDir(), "tmp" + _context.random().nextInt() + "-unzip");
|
||||
if (!FileUtil.extractZip(to, tempDir, Log.ERROR)) {
|
||||
f.delete();
|
||||
@ -406,7 +406,7 @@ class PluginUpdateRunner extends UpdateRunner {
|
||||
* @param pubkey null OK for su3
|
||||
* @since 0.9.15
|
||||
*/
|
||||
private void processFinal(File to, File appDir, String url, Properties props, String sudVersion, String pubkey, String signer) {
|
||||
protected void processFinal(File to, File appDir, String url, Properties props, String sudVersion, String pubkey, String signer) {
|
||||
boolean update = false;
|
||||
String appName = props.getProperty("name");
|
||||
String version = props.getProperty("version");
|
||||
|
@ -0,0 +1,94 @@
|
||||
package net.i2p.router.update;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import net.i2p.crypto.TrustedUpdate;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.web.ConfigUpdateHandler;
|
||||
import net.i2p.update.UpdateMethod;
|
||||
import net.i2p.update.UpdateType;
|
||||
import net.i2p.util.EepGet;
|
||||
import net.i2p.util.PartialEepGet;
|
||||
import net.i2p.util.PortMapper;
|
||||
|
||||
public class PluginUpdateTorrentChecker extends PluginUpdateChecker {
|
||||
private final String _appName;
|
||||
private final String _oldVersion;
|
||||
private final URI _torrentURI;
|
||||
|
||||
public PluginUpdateTorrentChecker(RouterContext ctx, ConsoleUpdateManager mgr,
|
||||
List<URI> uris, String appName, String oldVersion) {
|
||||
//super(ctx, mgr, UpdateType.PLUGIN, uris, oldVersion);
|
||||
super(ctx, mgr, uris, appName, oldVersion);
|
||||
if (!uris.isEmpty())
|
||||
_currentURI = uris.get(0);
|
||||
if (uris.size() == 2)
|
||||
_torrentURI = uris.get(1);
|
||||
else
|
||||
_torrentURI = null;
|
||||
_appName = appName;
|
||||
_oldVersion = oldVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
boolean torrentSeed = updateCheck(_torrentURI.toString(), true);
|
||||
if (!torrentSeed) {
|
||||
// No torrent update available, just use the HTTP update
|
||||
super.update();
|
||||
return;
|
||||
} else {
|
||||
// There's a torrent available
|
||||
//_mgr.notifyCheckComplete(this, true, true);
|
||||
boolean httpSeed = updateCheck(_currentURI.toString(), false);
|
||||
// use the HTTP-only check to determine if there's an update available using
|
||||
// PartialEepGet
|
||||
if (httpSeed) {
|
||||
// Here we know there is an update and a corresponding torrent.
|
||||
// We will check if the versions match before we peform the real update.
|
||||
_mgr.notifyCheckComplete(this, httpSeed, torrentSeed);
|
||||
} else {
|
||||
// HTTP-only update check failed, we know nothing(special)
|
||||
_mgr.notifyCheckComplete(this, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean updateCheck(String uriString, boolean torrent) {
|
||||
if (_torrentURI != null)
|
||||
return false;
|
||||
_isPartial = torrent;
|
||||
// performs exactly the same update check as PluginUpdateChecker
|
||||
// but returns a boolean value
|
||||
String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST,
|
||||
ConfigUpdateHandler.DEFAULT_PROXY_HOST);
|
||||
int proxyPort = ConfigUpdateHandler.proxyPort(_context);
|
||||
if (proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
|
||||
proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
|
||||
_context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) {
|
||||
String msg = _t("HTTP client proxy tunnel must be running");
|
||||
if (_log.shouldWarn())
|
||||
_log.warn(msg);
|
||||
updateStatus("<b>" + msg + "</b>");
|
||||
return false;
|
||||
}
|
||||
updateStatus("<b>" + _t("Checking for update of plugin {0}", _appName) + "</b>");
|
||||
_baos.reset();
|
||||
try {
|
||||
if (_isPartial)
|
||||
_get = new PartialEepGet(_context, proxyHost, proxyPort, _baos, uriString, TrustedUpdate.HEADER_BYTES);
|
||||
else
|
||||
_get = new EepGet(_context, true, proxyHost, proxyPort,
|
||||
0, 0, 0, null, _baos,
|
||||
uriString, false, null, null);
|
||||
if (torrent)
|
||||
_get.addStatusListener(this);
|
||||
return _get.fetch(CONNECT_TIMEOUT);
|
||||
} catch (Throwable t) {
|
||||
_log.error("Error checking update for plugin", t);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,456 @@
|
||||
package net.i2p.router.update;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.i2p.CoreVersion;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.crypto.SU3File;
|
||||
import net.i2p.crypto.TrustedUpdate;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.SigningPublicKey;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.web.ConfigUpdateHandler;
|
||||
import net.i2p.router.web.Messages;
|
||||
import net.i2p.router.web.PluginStarter;
|
||||
import net.i2p.router.web.RouterConsoleRunner;
|
||||
import net.i2p.update.*;
|
||||
import net.i2p.util.EepGet;
|
||||
import net.i2p.util.FileUtil;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.OrderedProperties;
|
||||
import net.i2p.util.PortMapper;
|
||||
import net.i2p.util.SecureDirectory;
|
||||
import net.i2p.util.SecureFile;
|
||||
import net.i2p.util.SimpleTimer2;
|
||||
import net.i2p.util.SystemVersion;
|
||||
import net.i2p.util.VersionComparator;
|
||||
|
||||
import org.klomp.snark.BandwidthListener;
|
||||
import org.klomp.snark.BitField;
|
||||
import org.klomp.snark.CompleteListener;
|
||||
import org.klomp.snark.I2PSnarkUtil;
|
||||
import org.klomp.snark.MagnetURI;
|
||||
import org.klomp.snark.MetaInfo;
|
||||
import org.klomp.snark.Snark;
|
||||
import org.klomp.snark.SnarkManager;
|
||||
import org.klomp.snark.Storage;
|
||||
import org.klomp.snark.comments.CommentSet;
|
||||
|
||||
/**
|
||||
* Check for an updated version of a plugin.
|
||||
* A plugin is a standard .sud file with a 40-byte signature,
|
||||
* a 16-byte version, and a .zip file.
|
||||
*
|
||||
* So we get the current version and update URL for the installed plugin,
|
||||
* then fetch the first 56 bytes of the URL, extract the version,
|
||||
* and compare.
|
||||
*
|
||||
* uri list must not be empty.
|
||||
*
|
||||
* Moved from web/ and turned into an UpdateTask.
|
||||
*
|
||||
* @since 0.9.4 moved from PluginUpdateHandler
|
||||
*/
|
||||
class PluginUpdateTorrentRunner extends PluginUpdateRunner implements CompleteListener {
|
||||
|
||||
private static final long MAX_LENGTH = 128 * 1024 * 1024;
|
||||
private static final long METAINFO_TIMEOUT = 60 * 60 * 1000;
|
||||
private static final long COMPLETE_TIMEOUT = 12 * 60 * 60 * 1000;
|
||||
private static final long CHECK_INTERVAL = 3 * 60 * 1000;
|
||||
|
||||
private final String _xpi2pURLTorrent;
|
||||
private boolean _isComplete = false;
|
||||
private boolean _hasMetaInfo = false;
|
||||
private String _errMsg = "";
|
||||
|
||||
private static final String XPI2P = "app.xpi2p";
|
||||
private static final String ZIP = XPI2P + ".zip";
|
||||
public static final String PLUGIN_DIR = PluginStarter.PLUGIN_DIR;
|
||||
private static final String PROP_ALLOW_NEW_KEYS = "routerconsole.allowUntrustedPlugins";
|
||||
private Snark _snark = null;
|
||||
|
||||
public PluginUpdateTorrentRunner(RouterContext ctx, ConsoleUpdateManager mgr, List<URI> uris,
|
||||
String appName, String oldVersion) {
|
||||
super(ctx, mgr, uris, appName, oldVersion);
|
||||
if (uris.size() == 2)
|
||||
_xpi2pURLTorrent = uris.get(1).toString();
|
||||
else
|
||||
_xpi2pURLTorrent = "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void update() {
|
||||
_updated = false;
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null) {
|
||||
super.update();
|
||||
return;
|
||||
}
|
||||
if (_xpi2pURLTorrent.endsWith(".torrent")) {
|
||||
updateStatus("<b>" + _t("Downloading plugin from {0}", _xpi2pURLTorrent) + "</b>");
|
||||
try {
|
||||
_get = new EepGet(_context, 1, _updateFile, _xpi2pURLTorrent, false);
|
||||
_get.fetch(CONNECT_TIMEOUT, -1, true ? INACTIVITY_TIMEOUT : NOPROXY_INACTIVITY_TIMEOUT);
|
||||
File uf = new File(_updateFile);
|
||||
if (uf.exists()) {
|
||||
FileInputStream fis = new FileInputStream(uf);
|
||||
MetaInfo torrent = new MetaInfo(fis);
|
||||
fis.close();
|
||||
MagnetURI magnet = new MagnetURI(_smgr.util(), torrent.toMagnetURI());
|
||||
byte[] ih = torrent.getInfoHash();
|
||||
_snark = _smgr.getTorrentByInfoHash(ih);
|
||||
if (_snark != null) {
|
||||
updateStatus(_snark);
|
||||
if (_snark.getMetaInfo() != null) {
|
||||
_hasMetaInfo = true;
|
||||
Storage storage = _snark.getStorage();
|
||||
if (storage != null && storage.complete())
|
||||
processComplete(_snark);
|
||||
}
|
||||
if (!_isComplete) {
|
||||
if (_snark.isStopped() && !_snark.isStarting())
|
||||
_snark.startTorrent();
|
||||
// we aren't a listener so we must poll
|
||||
new Watcher();
|
||||
}
|
||||
}
|
||||
String name = magnet.getName();
|
||||
String trackerURL = magnet.getTrackerURL();
|
||||
if (trackerURL == null && !_smgr.util().shouldUseDHT() &&
|
||||
!_smgr.util().shouldUseOpenTrackers()) {
|
||||
// but won't we use OT as a failsafe even if disabled?
|
||||
_mgr.notifyAttemptFailed(this, "No tracker, no DHT, no OT", null);
|
||||
}
|
||||
_snark = _smgr.addMagnet(name, ih, trackerURL, true, true, null, this);
|
||||
if (_snark != null) {
|
||||
updateStatus(
|
||||
"<b>" + _smgr.util().getString("Updating from {0}", linkify(torrent.toMagnetURI()))
|
||||
+ "</b>");
|
||||
new Timeout();
|
||||
}
|
||||
_updated = true;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
_log.error("Error downloading plugin", t);
|
||||
}
|
||||
} else {
|
||||
// attempt an HTTP update using the _xpi2pURL
|
||||
super.update();
|
||||
return;
|
||||
}
|
||||
if (_updated) {
|
||||
_mgr.notifyComplete(this, _newVersion, null);
|
||||
_mgr.notifyComplete(this, _errMsg);
|
||||
} else {
|
||||
_mgr.notifyTaskFailed(this, _errMsg, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden to change the "Updating I2P" text in super
|
||||
*
|
||||
* @since 0.9.35
|
||||
*/
|
||||
@Override
|
||||
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining,
|
||||
String url) {
|
||||
long d = currentWrite + bytesTransferred;
|
||||
String status = "<b>" + _t("Downloading plugin") + ": " + _appDisplayName + "</b>";
|
||||
_mgr.notifyProgress(this, status, d, d + bytesRemaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url,
|
||||
String outputFile, boolean notModified) {
|
||||
if (!(_xpi2pURL.startsWith("file:") || _method == UpdateMethod.FILE))
|
||||
updateStatus("<b>" + _t("Plugin downloaded") + ": " + _appDisplayName + "</b>");
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null) {
|
||||
_log.error("No SnarkManager, can't find plugin update");
|
||||
super.transferComplete(alreadyTransferred, bytesTransferred, bytesRemaining, url, outputFile, notModified);
|
||||
return;
|
||||
}
|
||||
String file = _snark.getBaseName();
|
||||
File f = new File(_smgr.getDataDir(), file);
|
||||
File appDir = new SecureDirectory(_context.getConfigDir(), PLUGIN_DIR);
|
||||
if ((!appDir.exists()) && (!appDir.mkdir())) {
|
||||
f.delete();
|
||||
statusDone("<b>" + _t("Cannot create plugin directory {0}", appDir.getAbsolutePath()) + "</b>");
|
||||
return;
|
||||
}
|
||||
boolean isSU3;
|
||||
try {
|
||||
isSU3 = isSU3File(f);
|
||||
} catch (IOException ioe) {
|
||||
f.delete();
|
||||
statusDone("<b>" + ioe + "</b>");
|
||||
return;
|
||||
}
|
||||
if (isSU3)
|
||||
processSU3(f, appDir, url);
|
||||
else
|
||||
processSUD(f, appDir, url);
|
||||
}
|
||||
|
||||
private void statusDone(String msg) {
|
||||
// if we fail, we will pass this back in notifyTaskFailed()
|
||||
_errMsg = msg;
|
||||
updateStatus(msg);
|
||||
}
|
||||
|
||||
private SnarkManager getSnarkManager() {
|
||||
return new SnarkManager(_context);
|
||||
}
|
||||
|
||||
public BandwidthListener getBandwidthListener() {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null)
|
||||
return null;
|
||||
return _smgr.getBandwidthListener();
|
||||
}
|
||||
|
||||
public boolean shouldAutoStart() {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null)
|
||||
return false;
|
||||
return _smgr.shouldAutoStart();
|
||||
}
|
||||
|
||||
public void locked_saveComments(Snark snark, CommentSet comments) {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null)
|
||||
return;
|
||||
_smgr.locked_saveComments(snark, comments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void torrentComplete(Snark snark) {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null)
|
||||
return;
|
||||
_smgr.torrentComplete(snark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(Snark snark) {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null)
|
||||
return;
|
||||
_smgr.updateStatus(snark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String gotMetaInfo(Snark snark) {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null)
|
||||
return null;
|
||||
return _smgr.gotMetaInfo(snark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatal(Snark snark, String error) {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null)
|
||||
return;
|
||||
_smgr.fatal(snark, error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMessage(Snark snark, String message) {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null)
|
||||
return;
|
||||
_smgr.addMessage(snark, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gotPiece(Snark snark) {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null)
|
||||
return;
|
||||
_smgr.gotPiece(snark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSavedTorrentTime(Snark snark) {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null)
|
||||
return 0;
|
||||
return _smgr.getSavedTorrentTime(snark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitField getSavedTorrentBitField(Snark snark) {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null)
|
||||
return null;
|
||||
return _smgr.getSavedTorrentBitField(snark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getSavedPreserveNamesSetting(Snark snark) {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null)
|
||||
return false;
|
||||
return _smgr.getSavedPreserveNamesSetting(snark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSavedUploaded(Snark snark) {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null)
|
||||
return 0;
|
||||
return _smgr.getSavedUploaded(snark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommentSet getSavedComments(Snark snark) {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null)
|
||||
return null;
|
||||
return _smgr.getSavedComments(snark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
if (_snark != null)
|
||||
_snark.startTorrent();
|
||||
}
|
||||
|
||||
private void processComplete(Snark snark) {
|
||||
String url = _snark.getMetaInfo().toMagnetURI();
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null) {
|
||||
_log.warn("No SnarkManager");
|
||||
return;
|
||||
}
|
||||
String dataFile = snark.getBaseName();
|
||||
File f = new File(_smgr.getDataDir(), dataFile);
|
||||
String sudVersion = TrustedUpdate.getVersionString(f);
|
||||
if (_newVersion.equals(sudVersion))
|
||||
_mgr.notifyComplete(this, _newVersion, f);
|
||||
else
|
||||
fatal("version mismatch");
|
||||
_isComplete = true;
|
||||
long alreadyTransferred = f.getAbsoluteFile().length();
|
||||
transferComplete(alreadyTransferred, alreadyTransferred, 0, _xpi2pURL, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will run twice, once at the metainfo timeout and
|
||||
* once at the complete timeout.
|
||||
*/
|
||||
private class Timeout extends SimpleTimer2.TimedEvent {
|
||||
private final long _start = _context.clock().now();
|
||||
|
||||
public Timeout() {
|
||||
super(_context.simpleTimer2(), METAINFO_TIMEOUT);
|
||||
}
|
||||
|
||||
public void timeReached() {
|
||||
if (_isComplete || !_isRunning)
|
||||
return;
|
||||
if (!_hasMetaInfo) {
|
||||
fatal("Metainfo timeout");
|
||||
return;
|
||||
}
|
||||
if (_context.clock().now() - _start >= COMPLETE_TIMEOUT) {
|
||||
fatal("Complete timeout");
|
||||
return;
|
||||
}
|
||||
reschedule(COMPLETE_TIMEOUT - METAINFO_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rarely used - only if the user added the torrent, so
|
||||
* we aren't a complete listener.
|
||||
* This will periodically until the complete timeout.
|
||||
*/
|
||||
private class Watcher extends SimpleTimer2.TimedEvent {
|
||||
private final long _start = _context.clock().now();
|
||||
|
||||
public Watcher() {
|
||||
super(_context.simpleTimer2(), CHECK_INTERVAL);
|
||||
}
|
||||
|
||||
public void timeReached() {
|
||||
if (_hasMetaInfo && _snark.getRemainingLength() == 0 && !_isComplete)
|
||||
processComplete(_snark);
|
||||
if (_isComplete || !_isRunning)
|
||||
return;
|
||||
if (_context.clock().now() - _start >= METAINFO_TIMEOUT && !_hasMetaInfo) {
|
||||
fatal("Metainfo timeout");
|
||||
return;
|
||||
}
|
||||
if (_context.clock().now() - _start >= COMPLETE_TIMEOUT) {
|
||||
fatal("Complete timeout");
|
||||
return;
|
||||
}
|
||||
notifyProgress();
|
||||
reschedule(CHECK_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
private void fatal(String error) {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null) {
|
||||
_log.warn("No SnarkManager");
|
||||
return;
|
||||
}
|
||||
if (_snark != null) {
|
||||
if (_hasMetaInfo) {
|
||||
// avoid loop stopTorrent() ... updateStatus() ... fatal() ...
|
||||
if (!_snark.isStopped())
|
||||
_smgr.stopTorrent(_snark, true);
|
||||
String file = _snark.getName();
|
||||
_smgr.removeTorrent(file);
|
||||
// delete torrent file
|
||||
File f = new File(_smgr.getDataDir(), file);
|
||||
f.delete();
|
||||
// delete data
|
||||
file = _snark.getBaseName();
|
||||
f = new File(_smgr.getDataDir(), file);
|
||||
f.delete();
|
||||
} else {
|
||||
_smgr.deleteMagnet(_snark);
|
||||
}
|
||||
}
|
||||
_mgr.notifyTaskFailed(this, error, null);
|
||||
_log.error(error);
|
||||
_isRunning = false;
|
||||
// stop the tunnel if we were the only one running
|
||||
if (_smgr.util().connected() && !_smgr.util().isConnecting()) {
|
||||
for (Snark s : _smgr.getTorrents()) {
|
||||
if (!s.isStopped())
|
||||
return;
|
||||
}
|
||||
_smgr.util().disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyProgress() {
|
||||
SnarkManager _smgr = getSnarkManager();
|
||||
if (_smgr == null) {
|
||||
_log.warn("No SnarkManager");
|
||||
return;
|
||||
}
|
||||
if (_hasMetaInfo && _snark != null) {
|
||||
long total = _snark.getTotalLength();
|
||||
long remaining = _snark.getRemainingLength();
|
||||
long transferred = total - remaining;
|
||||
String status = "<b>" + _smgr.util().getString("Updating") + "</b>";
|
||||
_mgr.notifyProgress(this, status, total - remaining, total);
|
||||
bytesTransferred(total, 0, transferred, remaining, _xpi2pURLTorrent);
|
||||
}
|
||||
}
|
||||
}
|
@ -379,7 +379,7 @@
|
||||
<copy file="apps/desktopgui/dist/desktopgui.jar" todir="build/" />
|
||||
</target>
|
||||
|
||||
<target name="buildRouterConsole" depends="buildrouter, buildSystray, buildDesktopGui, buildJetty, buildJrobin" >
|
||||
<target name="buildRouterConsole" depends="buildrouter, buildSystray, buildDesktopGui, buildJetty, buildJrobin, i2psnark" >
|
||||
<ant dir="apps/routerconsole/java/" target="jar" />
|
||||
</target>
|
||||
|
||||
|
Reference in New Issue
Block a user