* i2psnark:

- Improved magnet link parsing, use tr parameter if present
This commit is contained in:
zzz
2011-02-10 17:12:15 +00:00
parent 03bc4fc133
commit ae9c160734
6 changed files with 89 additions and 24 deletions

View File

@ -254,6 +254,7 @@ public class Snark
private boolean stopped; private boolean stopped;
private byte[] id; private byte[] id;
private byte[] infoHash; private byte[] infoHash;
private String additionalTrackerURL;
private final I2PSnarkUtil _util; private final I2PSnarkUtil _util;
private final PeerCoordinatorSet _peerCoordinatorSet; private final PeerCoordinatorSet _peerCoordinatorSet;
private String trackerProblems; private String trackerProblems;
@ -453,9 +454,10 @@ public class Snark
* *
* @param torrent a fake name for now (not a file name) * @param torrent a fake name for now (not a file name)
* @param ih 20-byte info hash * @param ih 20-byte info hash
* @param trackerURL may be null
* @since 0.8.4 * @since 0.8.4
*/ */
public Snark(I2PSnarkUtil util, String torrent, byte[] ih, public Snark(I2PSnarkUtil util, String torrent, byte[] ih, String trackerURL,
CompleteListener complistener, PeerCoordinatorSet peerCoordinatorSet, CompleteListener complistener, PeerCoordinatorSet peerCoordinatorSet,
ConnectionAcceptor connectionAcceptor, boolean start, String rootDir) ConnectionAcceptor connectionAcceptor, boolean start, String rootDir)
{ {
@ -465,6 +467,7 @@ public class Snark
acceptor = connectionAcceptor; acceptor = connectionAcceptor;
this.torrent = torrent; this.torrent = torrent;
this.infoHash = ih; this.infoHash = ih;
this.additionalTrackerURL = trackerURL;
this.rootDataDir = rootDir; this.rootDataDir = rootDir;
stopped = true; stopped = true;
id = generateID(); id = generateID();
@ -535,7 +538,7 @@ public class Snark
acceptor = new ConnectionAcceptor(_util, serversocket, new PeerAcceptor(coordinator)); acceptor = new ConnectionAcceptor(_util, serversocket, new PeerAcceptor(coordinator));
} }
// TODO pass saved closest DHT nodes to the tracker? or direct to the coordinator? // TODO pass saved closest DHT nodes to the tracker? or direct to the coordinator?
trackerclient = new TrackerClient(_util, meta, coordinator, this); trackerclient = new TrackerClient(_util, meta, additionalTrackerURL, coordinator, this);
} }
stopped = false; stopped = false;
@ -564,11 +567,13 @@ public class Snark
fatal("Could not reopen storage", ioe); fatal("Could not reopen storage", ioe);
} }
} }
TrackerClient newClient = new TrackerClient(_util, meta, coordinator, this); TrackerClient newClient = new TrackerClient(_util, meta, additionalTrackerURL, coordinator, this);
if (!trackerclient.halted()) if (!trackerclient.halted())
trackerclient.halt(); trackerclient.halt();
trackerclient = newClient; trackerclient = newClient;
trackerclient.start(); trackerclient.start();
} else {
debug("NOT starting TrackerClient???", NOTICE);
} }
} }
/** /**
@ -825,6 +830,14 @@ public class Snark
return true; return true;
} }
/**
* @return trackerURL string from magnet-mode constructor, may be null
* @since 0.8.4
*/
public String getTrackerURL() {
return additionalTrackerURL;
}
/** /**
* Sets debug, ip and torrent variables then creates a Snark * Sets debug, ip and torrent variables then creates a Snark
* instance. Calls usage(), which terminates the program, if * instance. Calls usage(), which terminates the program, if

View File

@ -643,11 +643,15 @@ public class SnarkManager implements Snark.CompleteListener {
* *
* @param name hex or b32 name from the magnet link * @param name hex or b32 name from the magnet link
* @param ih 20 byte info hash * @param ih 20 byte info hash
* @param trackerURL may be null
* @param udpateStatus should we add this magnet to the config file,
* to save it across restarts, in case we don't get
* the metadata before shutdown?
* @throws RuntimeException via Snark.fatal() * @throws RuntimeException via Snark.fatal()
* @since 0.8.4 * @since 0.8.4
*/ */
public void addMagnet(String name, byte[] ih, boolean updateStatus) { public void addMagnet(String name, byte[] ih, String trackerURL, boolean updateStatus) {
Snark torrent = new Snark(_util, name, ih, this, Snark torrent = new Snark(_util, name, ih, trackerURL, this,
_peerCoordinatorSet, _connectionAcceptor, _peerCoordinatorSet, _connectionAcceptor,
false, getDataDir().getPath()); false, getDataDir().getPath());
@ -1151,6 +1155,10 @@ public class SnarkManager implements Snark.CompleteListener {
saveTorrentStatus(meta, storage.getBitField(), null); // no file priorities saveTorrentStatus(meta, storage.getBitField(), null); // no file priorities
String name = (new File(getDataDir(), storage.getBaseName() + ".torrent")).getAbsolutePath(); String name = (new File(getDataDir(), storage.getBaseName() + ".torrent")).getAbsolutePath();
try { try {
// put the announce URL in the file
String announce = snark.getTrackerURL();
if (announce != null)
meta = meta.reannounce(announce);
synchronized (_snarks) { synchronized (_snarks) {
locked_writeMetaInfo(meta, name); locked_writeMetaInfo(meta, name);
// put it in the list under the new name // put it in the list under the new name
@ -1183,9 +1191,9 @@ public class SnarkManager implements Snark.CompleteListener {
String b64 = k.substring(PROP_META_MAGNET_PREFIX.length()); String b64 = k.substring(PROP_META_MAGNET_PREFIX.length());
b64 = b64.replace('$', '='); b64 = b64.replace('$', '=');
byte[] ih = Base64.decode(b64); byte[] ih = Base64.decode(b64);
// ignore value // ignore value - TODO put tracker URL in value
if (ih != null && ih.length == 20) if (ih != null && ih.length == 20)
addMagnet("Magnet: " + I2PSnarkUtil.toHex(ih), ih, false); addMagnet("Magnet: " + I2PSnarkUtil.toHex(ih), ih, null, false);
// else remove from config? // else remove from config?
} }
} }

View File

@ -65,6 +65,7 @@ public class TrackerClient extends I2PAppThread
private I2PSnarkUtil _util; private I2PSnarkUtil _util;
private final MetaInfo meta; private final MetaInfo meta;
private final String additionalTrackerURL;
private final PeerCoordinator coordinator; private final PeerCoordinator coordinator;
private final Snark snark; private final Snark snark;
private final int port; private final int port;
@ -76,8 +77,10 @@ public class TrackerClient extends I2PAppThread
/** /**
* @param meta null if in magnet mode * @param meta null if in magnet mode
* @param additionalTrackerURL may be null, from the ?tr= param in magnet mode, otherwise ignored
*/ */
public TrackerClient(I2PSnarkUtil util, MetaInfo meta, PeerCoordinator coordinator, Snark snark) public TrackerClient(I2PSnarkUtil util, MetaInfo meta, String additionalTrackerURL,
PeerCoordinator coordinator, Snark snark)
{ {
super(); super();
// Set unique name. // Set unique name.
@ -85,13 +88,11 @@ public class TrackerClient extends I2PAppThread
setName("TrackerClient " + id.substring(id.length() - 12)); setName("TrackerClient " + id.substring(id.length() - 12));
_util = util; _util = util;
this.meta = meta; this.meta = meta;
this.additionalTrackerURL = additionalTrackerURL;
this.coordinator = coordinator; this.coordinator = coordinator;
this.snark = snark; this.snark = snark;
this.port = 6881; //(port == -1) ? 9 : port; this.port = 6881; //(port == -1) ? 9 : port;
stop = false;
started = false;
} }
@Override @Override
@ -138,17 +139,21 @@ public class TrackerClient extends I2PAppThread
// todo: check for b32 matches as well // todo: check for b32 matches as well
trackers = new ArrayList(2); trackers = new ArrayList(2);
String primary = null; String primary = null;
if (meta != null) { if (meta != null)
primary = meta.getAnnounce(); primary = meta.getAnnounce();
else if (additionalTrackerURL != null)
primary = additionalTrackerURL;
if (primary != null) {
if (isValidAnnounce(primary)) { if (isValidAnnounce(primary)) {
trackers.add(new Tracker(meta.getAnnounce(), true)); trackers.add(new Tracker(primary, true));
_log.debug("Announce: [" + primary + "] infoHash: " + infoHash); _log.debug("Announce: [" + primary + "] infoHash: " + infoHash);
} else { } else {
_log.warn("Skipping invalid or non-i2p announce: " + primary); _log.warn("Skipping invalid or non-i2p announce: " + primary);
} }
} } else {
if (primary == null) _log.warn("No primary announce");
primary = ""; primary = "";
}
List tlist = _util.getOpenTrackers(); List tlist = _util.getOpenTrackers();
if (tlist != null) { if (tlist != null) {
for (int i = 0; i < tlist.size(); i++) { for (int i = 0; i < tlist.size(); i++) {

View File

@ -65,7 +65,8 @@ public class I2PSnarkServlet extends Default {
public static final String PROP_CONFIG_FILE = "i2psnark.configFile"; public static final String PROP_CONFIG_FILE = "i2psnark.configFile";
/** BEP 9 */ /** BEP 9 */
private static final String MAGNET = "magnet:?xt=urn:btih:"; private static final String MAGNET = "magnet:";
private static final String MAGNET_FULL = MAGNET + "?xt=urn:btih:";
/** http://sponge.i2p/files/maggotspec.txt */ /** http://sponge.i2p/files/maggotspec.txt */
private static final String MAGGOT = "maggot://"; private static final String MAGGOT = "maggot://";
@ -1406,13 +1407,22 @@ public class I2PSnarkServlet extends Default {
private void addMagnet(String url) { private void addMagnet(String url) {
String ihash; String ihash;
String name; String name;
String trackerURL = null;
if (url.startsWith(MAGNET)) { if (url.startsWith(MAGNET)) {
ihash = url.substring(MAGNET.length()).trim(); // magnet:?xt=urn:btih:0691e40aae02e552cfcb57af1dca56214680c0c5&tr=http://tracker2.postman.i2p/announce.php
int amp = ihash.indexOf('&'); String xt = getParam("xt", url);
if (amp >= 0) if (xt == null || !xt.startsWith("urn:btih:")) {
ihash = ihash.substring(0, amp); _manager.addMessage(_("Invalid magnet URL {0}", url));
return;
}
ihash = xt.substring("urn:btih:".length());
trackerURL = getParam("tr", url);
name = "Magnet " + ihash; name = "Magnet " + ihash;
String dn = getParam("dn", url);
if (dn != null)
name += " (" + Storage.filterName(dn) + ')';
} else if (url.startsWith(MAGGOT)) { } else if (url.startsWith(MAGGOT)) {
// maggot://0691e40aae02e552cfcb57af1dca56214680c0c5:0b557bbdf8718e95d352fbe994dec3a383e2ede7
ihash = url.substring(MAGGOT.length()).trim(); ihash = url.substring(MAGGOT.length()).trim();
int col = ihash.indexOf(':'); int col = ihash.indexOf(':');
if (col >= 0) if (col >= 0)
@ -1439,7 +1449,27 @@ public class I2PSnarkServlet extends Default {
_manager.addMessage(_("Invalid info hash in magnet URL {0}", url)); _manager.addMessage(_("Invalid info hash in magnet URL {0}", url));
return; return;
} }
_manager.addMagnet(name, ih, true); _manager.addMagnet(name, ih, trackerURL, true);
}
private static String getParam(String key, String uri) {
int idx = uri.indexOf('?' + key + '=');
if (idx >= 0) {
idx += key.length() + 2;
} else {
idx = uri.indexOf('&' + key + '=');
if (idx >= 0)
idx += key.length() + 2;
}
if (idx < 0 || idx > uri.length())
return null;
String rv = uri.substring(idx);
idx = rv.indexOf('&');
if (idx >= 0)
rv = rv.substring(0, idx);
else
rv = rv.trim();
return rv;
} }
/** copied from ConfigTunnelsHelper */ /** copied from ConfigTunnelsHelper */
@ -1644,8 +1674,8 @@ public class I2PSnarkServlet extends Default {
String hex = I2PSnarkUtil.toHex(snark.getInfoHash()); String hex = I2PSnarkUtil.toHex(snark.getInfoHash());
buf.append("<br>").append(toImg("magnet", _("Magnet link"))).append(" <a href=\"") buf.append("<br>").append(toImg("magnet", _("Magnet link"))).append(" <a href=\"")
.append(MAGNET).append(hex).append("\">") .append(MAGNET_FULL).append(hex).append("\">")
.append(MAGNET).append(hex).append("</a>"); .append(MAGNET_FULL).append(hex).append("</a>");
// We don't have the hash of the torrent file // We don't have the hash of the torrent file
//buf.append("<br>").append(_("Maggot link")).append(": <a href=\"").append(MAGGOT).append(hex).append(':').append(hex).append("\">") //buf.append("<br>").append(_("Maggot link")).append(": <a href=\"").append(MAGGOT).append(hex).append(':').append(hex).append("\">")
// .append(MAGGOT).append(hex).append(':').append(hex).append("</a>"); // .append(MAGGOT).append(hex).append(':').append(hex).append("</a>");

View File

@ -1,3 +1,12 @@
2011-02-10 zzz
* I2CP: Correctly close internal connections on the router side
when closed by the client, was causing massive memory leak
for internal clients using lots of sessions (thanks sponge)
* i2psnark:
- Improved magnet link parsing, use tr parameter if present
* i2ptunnel: Change shared clients default for new clients to false
* Streaming: Don't use iter.remove() on a COWAS
2011-02-09 sponge 2011-02-09 sponge
* BOB: fixup delivery in config, adds config file versioning. * BOB: fixup delivery in config, adds config file versioning.
* I2CP: Fix most of the I2CP leaks. Two leaks remain, but they are small. * I2CP: Fix most of the I2CP leaks. Two leaks remain, but they are small.

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */ /** deprecated */
public final static String ID = "Monotone"; public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION; public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 5; public final static long BUILD = 6;
/** for example "-test" */ /** for example "-test" */
public final static String EXTRA = ""; public final static String EXTRA = "";