diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index 81d72ee84e..6cd12be4c0 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -748,6 +748,14 @@ public class SnarkManager implements CompleteListener { */ public Snark getTorrent(String filename) { synchronized (_snarks) { return _snarks.get(filename); } } + /** + * Unmodifiable + * @since 0.9.4 + */ + public Collection getTorrents() { + return Collections.unmodifiableCollection(_snarks.values()); + } + /** * Grab the torrent given the base name of the storage * @return Snark or null diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index 21e006f5e4..7456624fe3 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -21,6 +21,7 @@ package org.klomp.snark; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.charset.Charset; @@ -34,8 +35,10 @@ import java.util.StringTokenizer; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; +import net.i2p.I2PAppContext; import net.i2p.crypto.SHA1; import net.i2p.data.ByteArray; +import net.i2p.data.DataHelper; import net.i2p.util.ByteCache; import net.i2p.util.Log; import net.i2p.util.SecureFile; @@ -1200,4 +1203,41 @@ public class Storage rafs[i] = null; } + /** + * Create a metainfo. + * Used in the installer build process; do not comment out. + * @since 0.9.4 + */ + public static void main(String[] args) { + if (args.length < 1 || args.length > 2) { + System.err.println("Usage: Storage file-or-dir [announceURL]"); + System.exit(1); + } + File base = new File(args[0]); + String announce = args.length == 2 ? args[1] : null; + I2PAppContext ctx = I2PAppContext.getGlobalContext(); + I2PSnarkUtil util = new I2PSnarkUtil(ctx); + File file = null; + FileOutputStream out = null; + try { + Storage storage = new Storage(util, base, announce, false, null); + MetaInfo meta = storage.getMetaInfo(); + file = new File(storage.getBaseName() + ".torrent"); + out = new FileOutputStream(file); + out.write(meta.getTorrentData()); + String hex = DataHelper.toString(meta.getInfoHash()); + System.out.println("Created: " + file); + System.out.println("InfoHash: " + hex); + String magnet = MagnetURI.MAGNET_FULL + hex; + if (announce != null) + magnet += "&tr=" + announce; + System.out.println("Magnet: " + magnet); + } catch (IOException ioe) { + if (file != null) + file.delete(); + ioe.printStackTrace(); + } finally { + try { if (out != null) out.close(); } catch (IOException ioe) {} + } + } } diff --git a/apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java b/apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java index 9699b70d7e..759026edca 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java +++ b/apps/i2psnark/java/src/org/klomp/snark/UpdateRunner.java @@ -82,8 +82,19 @@ class UpdateRunner implements UpdateTask, CompleteListener { String updateURL = uri.toString(); try { MagnetURI magnet = new MagnetURI(_smgr.util(), updateURL); - String name = magnet.getName(); byte[] ih = magnet.getInfoHash(); + // do we already have it? + _snark = _smgr.getTorrentByInfoHash(ih); + if (_snark != null) { + if (_snark.getMetaInfo() != null) { + _hasMetaInfo = true; + Storage storage = _snark.getStorage(); + if (storage != null && storage.complete()) + processComplete(_snark); + } + break; + } + String name = magnet.getName(); String trackerURL = magnet.getTrackerURL(); if (trackerURL == null && !_smgr.util().shouldUseDHT() && !_smgr.util().shouldUseOpenTrackers()) { @@ -151,21 +162,33 @@ class UpdateRunner implements UpdateTask, CompleteListener { _umgr.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 processComplete(Snark snark) { + String dataFile = snark.getBaseName(); + File f = new File(_smgr.getDataDir(), dataFile); + String sudVersion = TrustedUpdate.getVersionString(f); + if (_newVersion.equals(sudVersion)) + _umgr.notifyComplete(this, _newVersion, f); + else + fatal("version mismatch"); + _isComplete = true; } //////// begin CompleteListener methods //////// all pass through to SnarkManager public void torrentComplete(Snark snark) { - String dataFile = snark.getBaseName(); - File f = new File(_smgr.getDataDir(), dataFile); - String sudVersion = TrustedUpdate.getVersionString(f); - if (!_newVersion.equals(sudVersion)) { - fatal("version mismatch"); - } - _umgr.notifyComplete(this, _newVersion, f); + processComplete(snark); _smgr.torrentComplete(snark); - _isComplete = true; } /** diff --git a/build.xml b/build.xml index c819e242cb..f4831bceaa 100644 --- a/build.xml +++ b/build.xml @@ -1553,6 +1553,23 @@ + + + + + + + + + + + + + + + + +