forked from I2P_Developers/i2p.i2p
stub of a torrent updater
This commit is contained in:
@ -889,7 +889,27 @@ public class SnarkManager implements CompleteListener {
|
|||||||
* @since 0.8.4
|
* @since 0.8.4
|
||||||
*/
|
*/
|
||||||
public void addMagnet(String name, byte[] ih, String trackerURL, boolean updateStatus) {
|
public void addMagnet(String name, byte[] ih, String trackerURL, boolean updateStatus) {
|
||||||
Snark torrent = new Snark(_util, name, ih, trackerURL, this,
|
addMagnet(name, ih, trackerURL, updateStatus, shouldAutoStart(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a torrent with the info hash alone (magnet / maggot)
|
||||||
|
* External use is for UpdateRunner.
|
||||||
|
*
|
||||||
|
* @param name hex or b32 name from the magnet link
|
||||||
|
* @param ih 20 byte info hash
|
||||||
|
* @param trackerURL may be null
|
||||||
|
* @param updateStatus should we add this magnet to the config file,
|
||||||
|
* to save it across restarts, in case we don't get
|
||||||
|
* the metadata before shutdown?
|
||||||
|
* @param listener to intercept callbacks, should pass through to this
|
||||||
|
* @return the new Snark or null on failure
|
||||||
|
* @throws RuntimeException via Snark.fatal()
|
||||||
|
* @since 0.9.4
|
||||||
|
*/
|
||||||
|
public Snark addMagnet(String name, byte[] ih, String trackerURL, boolean updateStatus,
|
||||||
|
boolean autoStart, CompleteListener listener) {
|
||||||
|
Snark torrent = new Snark(_util, name, ih, trackerURL, listener,
|
||||||
_peerCoordinatorSet, _connectionAcceptor,
|
_peerCoordinatorSet, _connectionAcceptor,
|
||||||
false, getDataDir().getPath());
|
false, getDataDir().getPath());
|
||||||
|
|
||||||
@ -897,7 +917,7 @@ public class SnarkManager implements CompleteListener {
|
|||||||
Snark snark = getTorrentByInfoHash(ih);
|
Snark snark = getTorrentByInfoHash(ih);
|
||||||
if (snark != null) {
|
if (snark != null) {
|
||||||
addMessage(_("Torrent with this info hash is already running: {0}", snark.getBaseName()));
|
addMessage(_("Torrent with this info hash is already running: {0}", snark.getBaseName()));
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
// Tell the dir monitor not to delete us
|
// Tell the dir monitor not to delete us
|
||||||
_magnets.add(name);
|
_magnets.add(name);
|
||||||
@ -905,7 +925,7 @@ public class SnarkManager implements CompleteListener {
|
|||||||
saveMagnetStatus(ih);
|
saveMagnetStatus(ih);
|
||||||
_snarks.put(name, torrent);
|
_snarks.put(name, torrent);
|
||||||
}
|
}
|
||||||
if (shouldAutoStart()) {
|
if (autoStart) {
|
||||||
torrent.startTorrent();
|
torrent.startTorrent();
|
||||||
addMessage(_("Fetching {0}", name));
|
addMessage(_("Fetching {0}", name));
|
||||||
DHT dht = _util.getDHT();
|
DHT dht = _util.getDHT();
|
||||||
@ -919,6 +939,7 @@ public class SnarkManager implements CompleteListener {
|
|||||||
} else {
|
} else {
|
||||||
addMessage(_("Adding {0}", name));
|
addMessage(_("Adding {0}", name));
|
||||||
}
|
}
|
||||||
|
return torrent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
54
apps/i2psnark/java/src/org/klomp/snark/UpdateHandler.java
Normal file
54
apps/i2psnark/java/src/org/klomp/snark/UpdateHandler.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package org.klomp.snark;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.update.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Handles the request to update the router by firing up a magnet.
|
||||||
|
* {@link net.i2p.util.EepGet} calls to download the latest signed update file
|
||||||
|
* and displaying the status to anyone who asks.
|
||||||
|
* </p>
|
||||||
|
* <p>After the download completes the signed update file is verified with
|
||||||
|
* {@link net.i2p.crypto.TrustedUpdate}, and if it's authentic the payload
|
||||||
|
* of the signed update file is unpacked and the router is restarted to complete
|
||||||
|
* the update process.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* This does not do any checking, that is handled by the NewsFetcher.
|
||||||
|
*
|
||||||
|
* @since 0.9.4
|
||||||
|
*/
|
||||||
|
public class UpdateHandler implements Updater {
|
||||||
|
private final I2PAppContext _context;
|
||||||
|
private final UpdateManager _umgr;
|
||||||
|
private final SnarkManager _smgr;
|
||||||
|
|
||||||
|
public UpdateHandler(I2PAppContext ctx, UpdateManager umgr, SnarkManager smgr) {
|
||||||
|
_context = ctx;
|
||||||
|
_umgr = umgr;
|
||||||
|
_smgr = smgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a download and return a handle to the download task.
|
||||||
|
* Should not block.
|
||||||
|
*
|
||||||
|
* @param id plugin name or ignored
|
||||||
|
* @param maxTime how long you have
|
||||||
|
* @return active task or null if unable to download
|
||||||
|
*/
|
||||||
|
public UpdateTask update(UpdateType type, UpdateMethod method, List<URI> updateSources,
|
||||||
|
String id, String newVersion, long maxTime) {
|
||||||
|
if (type != UpdateType.ROUTER_SIGNED ||
|
||||||
|
method != UpdateMethod.TORRENT || updateSources.isEmpty())
|
||||||
|
return null;
|
||||||
|
UpdateRunner update = new UpdateRunner(_context, _umgr, _smgr, updateSources, newVersion);
|
||||||
|
// set status before thread to ensure UI feedback
|
||||||
|
_umgr.notifyProgress(update, "<b>" + _smgr.util().getString("Updating") + "</b>");
|
||||||
|
update.start();
|
||||||
|
return update;
|
||||||
|
}
|
||||||
|
}
|
149
apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java
Normal file
149
apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
package org.klomp.snark;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.crypto.TrustedUpdate;
|
||||||
|
import net.i2p.data.DataHelper;
|
||||||
|
import net.i2p.update.*;
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
import net.i2p.util.VersionComparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The downloader for router signed updates.
|
||||||
|
*
|
||||||
|
* @since 0.9.4
|
||||||
|
*/
|
||||||
|
class UpdateRunner implements UpdateTask, CompleteListener {
|
||||||
|
private final I2PAppContext _context;
|
||||||
|
private final Log _log;
|
||||||
|
private final UpdateManager _umgr;
|
||||||
|
private final SnarkManager _smgr;
|
||||||
|
private final List<URI> _urls;
|
||||||
|
private final String _updateFile;
|
||||||
|
private volatile boolean _isRunning;
|
||||||
|
private final String _newVersion;
|
||||||
|
private ByteArrayOutputStream _baos;
|
||||||
|
private URI _currentURI;
|
||||||
|
private Snark _snark;
|
||||||
|
|
||||||
|
private static final long CONNECT_TIMEOUT = 55*1000;
|
||||||
|
private static final long INACTIVITY_TIMEOUT = 5*60*1000;
|
||||||
|
private static final long NOPROXY_INACTIVITY_TIMEOUT = 60*1000;
|
||||||
|
|
||||||
|
public UpdateRunner(I2PAppContext ctx, UpdateManager umgr, SnarkManager smgr,
|
||||||
|
List<URI> uris, String newVersion) {
|
||||||
|
_context = ctx;
|
||||||
|
_log = ctx.logManager().getLog(getClass());
|
||||||
|
_umgr = umgr;
|
||||||
|
_smgr = smgr;
|
||||||
|
_urls = uris;
|
||||||
|
_newVersion = newVersion;
|
||||||
|
_updateFile = (new File(ctx.getTempDir(), "update" + ctx.random().nextInt() + ".tmp")).getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////// begin UpdateTask methods
|
||||||
|
|
||||||
|
public boolean isRunning() { return _isRunning; }
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
_isRunning = false;
|
||||||
|
if (_snark != null) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UpdateType getType() { return UpdateType.ROUTER_SIGNED; }
|
||||||
|
|
||||||
|
public UpdateMethod getMethod() { return UpdateMethod.TORRENT; }
|
||||||
|
|
||||||
|
public URI getURI() { return _currentURI; }
|
||||||
|
|
||||||
|
public String getID() { return ""; }
|
||||||
|
|
||||||
|
//////// end UpdateTask methods
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
_isRunning = true;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loop through the entire list of update URLs.
|
||||||
|
* For each one, first get the version from the first 56 bytes and see if
|
||||||
|
* it is newer than what we are running now.
|
||||||
|
* If it is, get the whole thing.
|
||||||
|
*/
|
||||||
|
private void update() {
|
||||||
|
|
||||||
|
if (_urls.isEmpty()) {
|
||||||
|
_umgr.notifyTaskFailed(this, "", null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (URI uri : _urls) {
|
||||||
|
_currentURI = uri;
|
||||||
|
String updateURL = uri.toString();
|
||||||
|
try {
|
||||||
|
MagnetURI magnet = new MagnetURI(_smgr.util(), updateURL);
|
||||||
|
String name = magnet.getName();
|
||||||
|
byte[] ih = magnet.getInfoHash();
|
||||||
|
String trackerURL = magnet.getTrackerURL();
|
||||||
|
_snark = _smgr.addMagnet(name, ih, trackerURL, true, true, this);
|
||||||
|
if (_snark != null) {
|
||||||
|
updateStatus("<b>" + _smgr.util().getString("Updating from {0}", updateURL) + "</b>");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException iae) {}
|
||||||
|
}
|
||||||
|
if (_snark == null) {
|
||||||
|
_umgr.notifyTaskFailed(this, "", null);
|
||||||
|
_isRunning = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////// begin CompleteListener methods
|
||||||
|
//////// all pass through to SnarkManager
|
||||||
|
|
||||||
|
public void torrentComplete(Snark snark) {
|
||||||
|
|
||||||
|
_smgr.torrentComplete(snark);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateStatus(Snark snark) {
|
||||||
|
|
||||||
|
_smgr.updateStatus(snark);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String gotMetaInfo(Snark snark) {
|
||||||
|
|
||||||
|
return _smgr.gotMetaInfo(snark);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fatal(Snark snark, String error) {
|
||||||
|
_smgr.fatal(snark, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addMessage(Snark snark, String message) {
|
||||||
|
_smgr.addMessage(snark, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSavedTorrentTime(Snark snark) {
|
||||||
|
return _smgr.getSavedTorrentTime(snark);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitField getSavedTorrentBitField(Snark snark) {
|
||||||
|
return _smgr.getSavedTorrentBitField(snark);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////// end CompleteListener methods
|
||||||
|
|
||||||
|
private void updateStatus(String s) {
|
||||||
|
_umgr.notifyProgress(this, s);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user