From 7ac673cea4cf48c16ec78ec755d8b77fd62d9ced Mon Sep 17 00:00:00 2001 From: jrandom Date: Tue, 13 Dec 2005 09:38:51 +0000 Subject: [PATCH] 2005-12-13 jrandom * Fixed I2PSnark's handling of some torrent files to deal with those created by Azureus and I2PRufus (it didn't know how to deal with additional meta info, such as path.utf-8 or name.utf-8). --- .../src/org/klomp/snark/I2PSnarkUtil.java | 12 +++- .../java/src/org/klomp/snark/MetaInfo.java | 62 +++++++++++++++++-- .../java/src/org/klomp/snark/Storage.java | 2 +- .../src/org/klomp/snark/TrackerClient.java | 9 ++- history.txt | 7 ++- 5 files changed, 82 insertions(+), 10 deletions(-) diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java index deda083cf..c0ebf0fca 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java +++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java @@ -86,17 +86,23 @@ public class I2PSnarkUtil { * fetch the given URL, returning the file it is stored in, or null on error */ File get(String url) { + _log.debug("Fetching [" + url + "] proxy=" + _proxyHost + ":" + _proxyPort + ": " + _shouldProxy); File out = null; try { out = File.createTempFile("i2psnark", "url"); } catch (IOException ioe) { ioe.printStackTrace(); + out.delete(); return null; } - EepGet get = new EepGet(_context, _shouldProxy, _proxyHost, _proxyPort, 1, out.getAbsolutePath(), url); + String fetchURL = rewriteAnnounce(url); + _log.debug("Rewritten url [" + fetchURL + "]"); + EepGet get = new EepGet(_context, _shouldProxy, _proxyHost, _proxyPort, 1, out.getAbsolutePath(), fetchURL); if (get.fetch()) { + _log.debug("Fetch successful [" + url + "]: size=" + out.length()); return out; } else { + _log.warn("Fetch failed [" + url + "]"); out.delete(); return null; } @@ -138,7 +144,9 @@ public class I2PSnarkUtil { int destStart = "http://".length(); int destEnd = origAnnounce.indexOf(".i2p"); int pathStart = origAnnounce.indexOf('/', destEnd); - return "http://i2p/" + origAnnounce.substring(destStart, destEnd) + origAnnounce.substring(pathStart); + String rv = "http://i2p/" + origAnnounce.substring(destStart, destEnd) + origAnnounce.substring(pathStart); + _log.debug("Rewriting [" + origAnnounce + "] as [" + rv + "]"); + return rv; } /** hook between snark's logger and an i2p log */ diff --git a/apps/i2psnark/java/src/org/klomp/snark/MetaInfo.java b/apps/i2psnark/java/src/org/klomp/snark/MetaInfo.java index e63b7803d..44fcdeab4 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/MetaInfo.java +++ b/apps/i2psnark/java/src/org/klomp/snark/MetaInfo.java @@ -33,13 +33,24 @@ import java.util.Map; import java.util.HashMap; import org.klomp.snark.bencode.*; +import net.i2p.data.Base64; +import net.i2p.util.Log; +/** + * Note: this class is buggy, as it doesn't propogate custom meta fields into the bencoded + * info data, and from there to the info_hash. At the moment, though, it seems to work with + * torrents created by I2P-BT, I2PRufus and Azureus. + * + */ public class MetaInfo -{ +{ + private static final Log _log = new Log(MetaInfo.class); private final String announce; private final byte[] info_hash; private final String name; + private final String name_utf8; private final List files; + private final List files_utf8; private final List lengths; private final int piece_length; private final byte[] piece_hashes; @@ -47,12 +58,14 @@ public class MetaInfo private byte[] torrentdata; - MetaInfo(String announce, String name, List files, List lengths, + MetaInfo(String announce, String name, String name_utf8, List files, List lengths, int piece_length, byte[] piece_hashes, long length) { this.announce = announce; this.name = name; + this.name_utf8 = name_utf8; this.files = files; + this.files_utf8 = null; this.lengths = lengths; this.piece_length = piece_length; this.piece_hashes = piece_hashes; @@ -90,6 +103,7 @@ public class MetaInfo */ public MetaInfo(Map m) throws InvalidBEncodingException { + _log.debug("Creating a metaInfo: " + m, new Exception("source")); BEValue val = (BEValue)m.get("announce"); if (val == null) throw new InvalidBEncodingException("Missing announce string"); @@ -105,6 +119,12 @@ public class MetaInfo throw new InvalidBEncodingException("Missing name string"); name = val.getString(); + val = (BEValue)info.get("name.utf-8"); + if (val != null) + name_utf8 = val.getString(); + else + name_utf8 = null; + val = (BEValue)info.get("piece length"); if (val == null) throw new InvalidBEncodingException("Missing piece length number"); @@ -121,6 +141,7 @@ public class MetaInfo // Single file case. length = val.getLong(); files = null; + files_utf8 = null; lengths = null; } else @@ -137,6 +158,7 @@ public class MetaInfo throw new InvalidBEncodingException("zero size files list"); files = new ArrayList(size); + files_utf8 = new ArrayList(size); lengths = new ArrayList(size); long l = 0; for (int i = 0; i < list.size(); i++) @@ -163,6 +185,19 @@ public class MetaInfo file.add(((BEValue)it.next()).getString()); files.add(file); + + val = (BEValue)desc.get("path.utf-8"); + if (val != null) { + path_list = val.getList(); + path_length = path_list.size(); + if (path_length > 0) { + file = new ArrayList(path_length); + it = path_list.iterator(); + while (it.hasNext()) + file.add(((BEValue)it.next()).getString()); + files_utf8.add(file); + } + } } length = l; } @@ -322,7 +357,7 @@ public class MetaInfo */ public MetaInfo reannounce(String announce) { - return new MetaInfo(announce, name, files, + return new MetaInfo(announce, name, name_utf8, files, lengths, piece_length, piece_hashes, length); } @@ -344,6 +379,8 @@ public class MetaInfo { Map info = new HashMap(); info.put("name", name); + if (name_utf8 != null) + info.put("name.utf-8", name_utf8); info.put("piece length", new Integer(piece_length)); info.put("pieces", piece_hashes); if (files == null) @@ -355,6 +392,8 @@ public class MetaInfo { Map file = new HashMap(); file.put("path", files.get(i)); + if ( (files_utf8 != null) && (files_utf8.size() > i) ) + file.put("path.utf-8", files_utf8.get(i)); file.put("length", lengths.get(i)); l.add(file); } @@ -366,11 +405,26 @@ public class MetaInfo private byte[] calculateInfoHash() { Map info = createInfoMap(); + StringBuffer buf = new StringBuffer(128); + buf.append("info: "); + for (Iterator iter = info.keySet().iterator(); iter.hasNext(); ) { + String key = (String)iter.next(); + Object val = info.get(key); + buf.append(key).append('='); + if (val instanceof byte[]) + buf.append(Base64.encode((byte[])val, true)); + else + buf.append(val.toString()); + } + _log.debug(buf.toString()); byte[] infoBytes = BEncoder.bencode(info); + _log.debug("info bencoded: [" + Base64.encode(infoBytes, true) + "]"); try { MessageDigest digest = MessageDigest.getInstance("SHA"); - return digest.digest(infoBytes); + byte hash[] = digest.digest(infoBytes); + _log.debug("info hash: [" + net.i2p.data.Base64.encode(hash) + "]"); + return hash; } catch(NoSuchAlgorithmException nsa) { diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index 287abf216..f4c53bb46 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -121,7 +121,7 @@ public class Storage } // Note that the piece_hashes are not correctly setup yet. - metainfo = new MetaInfo(announce, baseFile.getName(), files, + metainfo = new MetaInfo(announce, baseFile.getName(), null, files, lengthsList, piece_size, piece_hashes, total); } diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java index 49939311e..5cf91973f 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java +++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java @@ -25,6 +25,7 @@ import java.net.*; import java.util.*; import org.klomp.snark.bencode.*; +import net.i2p.util.Log; /** * Informs metainfo tracker of events and gets new peers for peer @@ -34,6 +35,7 @@ import org.klomp.snark.bencode.*; */ public class TrackerClient extends Thread { + private static final Log _log = new Log(TrackerClient.class); private static final String NO_EVENT = ""; private static final String STARTED_EVENT = "started"; private static final String COMPLETED_EVENT = "completed"; @@ -74,10 +76,13 @@ public class TrackerClient extends Thread public void run() { // XXX - Support other IPs - String announce = I2PSnarkUtil.instance().rewriteAnnounce(meta.getAnnounce()); + String announce = meta.getAnnounce(); //I2PSnarkUtil.instance().rewriteAnnounce(meta.getAnnounce()); String infoHash = urlencode(meta.getInfoHash()); String peerID = urlencode(coordinator.getID()); + _log.debug("Announce: [" + meta.getAnnounce() + "] infoHash: " + infoHash + + " xmitAnnounce: [" + announce + "]"); + long uploaded = coordinator.getUploaded(); long downloaded = coordinator.getDownloaded(); long left = coordinator.getLeft(); @@ -203,7 +208,7 @@ public class TrackerClient extends Thread + "?info_hash=" + infoHash + "&peer_id=" + peerID + "&port=" + port - + "&ip=" + I2PSnarkUtil.instance().getOurIPString() + + "&ip=" + I2PSnarkUtil.instance().getOurIPString() + ".i2p" + "&uploaded=" + uploaded + "&downloaded=" + downloaded + "&left=" + left diff --git a/history.txt b/history.txt index 553e0093e..e9b6d3f4a 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,9 @@ -$Id: history.txt,v 1.351 2005/12/08 15:53:43 jrandom Exp $ +$Id: history.txt,v 1.352 2005/12/09 03:05:48 jrandom Exp $ + +2005-12-13 jrandom + * Fixed I2PSnark's handling of some torrent files to deal with those + created by Azureus and I2PRufus (it didn't know how to deal with + additional meta info, such as path.utf-8 or name.utf-8). 2005-12-09 zzz * Create different strategies for exploratory tunnels (which are difficult