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).
This commit is contained in:
@ -86,17 +86,23 @@ public class I2PSnarkUtil {
|
|||||||
* fetch the given URL, returning the file it is stored in, or null on error
|
* fetch the given URL, returning the file it is stored in, or null on error
|
||||||
*/
|
*/
|
||||||
File get(String url) {
|
File get(String url) {
|
||||||
|
_log.debug("Fetching [" + url + "] proxy=" + _proxyHost + ":" + _proxyPort + ": " + _shouldProxy);
|
||||||
File out = null;
|
File out = null;
|
||||||
try {
|
try {
|
||||||
out = File.createTempFile("i2psnark", "url");
|
out = File.createTempFile("i2psnark", "url");
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
ioe.printStackTrace();
|
ioe.printStackTrace();
|
||||||
|
out.delete();
|
||||||
return null;
|
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()) {
|
if (get.fetch()) {
|
||||||
|
_log.debug("Fetch successful [" + url + "]: size=" + out.length());
|
||||||
return out;
|
return out;
|
||||||
} else {
|
} else {
|
||||||
|
_log.warn("Fetch failed [" + url + "]");
|
||||||
out.delete();
|
out.delete();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -138,7 +144,9 @@ public class I2PSnarkUtil {
|
|||||||
int destStart = "http://".length();
|
int destStart = "http://".length();
|
||||||
int destEnd = origAnnounce.indexOf(".i2p");
|
int destEnd = origAnnounce.indexOf(".i2p");
|
||||||
int pathStart = origAnnounce.indexOf('/', destEnd);
|
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 */
|
/** hook between snark's logger and an i2p log */
|
||||||
|
@ -33,13 +33,24 @@ import java.util.Map;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import org.klomp.snark.bencode.*;
|
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
|
public class MetaInfo
|
||||||
{
|
{
|
||||||
|
private static final Log _log = new Log(MetaInfo.class);
|
||||||
private final String announce;
|
private final String announce;
|
||||||
private final byte[] info_hash;
|
private final byte[] info_hash;
|
||||||
private final String name;
|
private final String name;
|
||||||
|
private final String name_utf8;
|
||||||
private final List files;
|
private final List files;
|
||||||
|
private final List files_utf8;
|
||||||
private final List lengths;
|
private final List lengths;
|
||||||
private final int piece_length;
|
private final int piece_length;
|
||||||
private final byte[] piece_hashes;
|
private final byte[] piece_hashes;
|
||||||
@ -47,12 +58,14 @@ public class MetaInfo
|
|||||||
|
|
||||||
private byte[] torrentdata;
|
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)
|
int piece_length, byte[] piece_hashes, long length)
|
||||||
{
|
{
|
||||||
this.announce = announce;
|
this.announce = announce;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.name_utf8 = name_utf8;
|
||||||
this.files = files;
|
this.files = files;
|
||||||
|
this.files_utf8 = null;
|
||||||
this.lengths = lengths;
|
this.lengths = lengths;
|
||||||
this.piece_length = piece_length;
|
this.piece_length = piece_length;
|
||||||
this.piece_hashes = piece_hashes;
|
this.piece_hashes = piece_hashes;
|
||||||
@ -90,6 +103,7 @@ public class MetaInfo
|
|||||||
*/
|
*/
|
||||||
public MetaInfo(Map m) throws InvalidBEncodingException
|
public MetaInfo(Map m) throws InvalidBEncodingException
|
||||||
{
|
{
|
||||||
|
_log.debug("Creating a metaInfo: " + m, new Exception("source"));
|
||||||
BEValue val = (BEValue)m.get("announce");
|
BEValue val = (BEValue)m.get("announce");
|
||||||
if (val == null)
|
if (val == null)
|
||||||
throw new InvalidBEncodingException("Missing announce string");
|
throw new InvalidBEncodingException("Missing announce string");
|
||||||
@ -105,6 +119,12 @@ public class MetaInfo
|
|||||||
throw new InvalidBEncodingException("Missing name string");
|
throw new InvalidBEncodingException("Missing name string");
|
||||||
name = val.getString();
|
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");
|
val = (BEValue)info.get("piece length");
|
||||||
if (val == null)
|
if (val == null)
|
||||||
throw new InvalidBEncodingException("Missing piece length number");
|
throw new InvalidBEncodingException("Missing piece length number");
|
||||||
@ -121,6 +141,7 @@ public class MetaInfo
|
|||||||
// Single file case.
|
// Single file case.
|
||||||
length = val.getLong();
|
length = val.getLong();
|
||||||
files = null;
|
files = null;
|
||||||
|
files_utf8 = null;
|
||||||
lengths = null;
|
lengths = null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -137,6 +158,7 @@ public class MetaInfo
|
|||||||
throw new InvalidBEncodingException("zero size files list");
|
throw new InvalidBEncodingException("zero size files list");
|
||||||
|
|
||||||
files = new ArrayList(size);
|
files = new ArrayList(size);
|
||||||
|
files_utf8 = new ArrayList(size);
|
||||||
lengths = new ArrayList(size);
|
lengths = new ArrayList(size);
|
||||||
long l = 0;
|
long l = 0;
|
||||||
for (int i = 0; i < list.size(); i++)
|
for (int i = 0; i < list.size(); i++)
|
||||||
@ -163,6 +185,19 @@ public class MetaInfo
|
|||||||
file.add(((BEValue)it.next()).getString());
|
file.add(((BEValue)it.next()).getString());
|
||||||
|
|
||||||
files.add(file);
|
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;
|
length = l;
|
||||||
}
|
}
|
||||||
@ -322,7 +357,7 @@ public class MetaInfo
|
|||||||
*/
|
*/
|
||||||
public MetaInfo reannounce(String announce)
|
public MetaInfo reannounce(String announce)
|
||||||
{
|
{
|
||||||
return new MetaInfo(announce, name, files,
|
return new MetaInfo(announce, name, name_utf8, files,
|
||||||
lengths, piece_length,
|
lengths, piece_length,
|
||||||
piece_hashes, length);
|
piece_hashes, length);
|
||||||
}
|
}
|
||||||
@ -344,6 +379,8 @@ public class MetaInfo
|
|||||||
{
|
{
|
||||||
Map info = new HashMap();
|
Map info = new HashMap();
|
||||||
info.put("name", name);
|
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("piece length", new Integer(piece_length));
|
||||||
info.put("pieces", piece_hashes);
|
info.put("pieces", piece_hashes);
|
||||||
if (files == null)
|
if (files == null)
|
||||||
@ -355,6 +392,8 @@ public class MetaInfo
|
|||||||
{
|
{
|
||||||
Map file = new HashMap();
|
Map file = new HashMap();
|
||||||
file.put("path", files.get(i));
|
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));
|
file.put("length", lengths.get(i));
|
||||||
l.add(file);
|
l.add(file);
|
||||||
}
|
}
|
||||||
@ -366,11 +405,26 @@ public class MetaInfo
|
|||||||
private byte[] calculateInfoHash()
|
private byte[] calculateInfoHash()
|
||||||
{
|
{
|
||||||
Map info = createInfoMap();
|
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);
|
byte[] infoBytes = BEncoder.bencode(info);
|
||||||
|
_log.debug("info bencoded: [" + Base64.encode(infoBytes, true) + "]");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
MessageDigest digest = MessageDigest.getInstance("SHA");
|
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)
|
catch(NoSuchAlgorithmException nsa)
|
||||||
{
|
{
|
||||||
|
@ -121,7 +121,7 @@ public class Storage
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Note that the piece_hashes are not correctly setup yet.
|
// 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);
|
lengthsList, piece_size, piece_hashes, total);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import java.net.*;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import org.klomp.snark.bencode.*;
|
import org.klomp.snark.bencode.*;
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Informs metainfo tracker of events and gets new peers for peer
|
* 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
|
public class TrackerClient extends Thread
|
||||||
{
|
{
|
||||||
|
private static final Log _log = new Log(TrackerClient.class);
|
||||||
private static final String NO_EVENT = "";
|
private static final String NO_EVENT = "";
|
||||||
private static final String STARTED_EVENT = "started";
|
private static final String STARTED_EVENT = "started";
|
||||||
private static final String COMPLETED_EVENT = "completed";
|
private static final String COMPLETED_EVENT = "completed";
|
||||||
@ -74,10 +76,13 @@ public class TrackerClient extends Thread
|
|||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
// XXX - Support other IPs
|
// 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 infoHash = urlencode(meta.getInfoHash());
|
||||||
String peerID = urlencode(coordinator.getID());
|
String peerID = urlencode(coordinator.getID());
|
||||||
|
|
||||||
|
_log.debug("Announce: [" + meta.getAnnounce() + "] infoHash: " + infoHash
|
||||||
|
+ " xmitAnnounce: [" + announce + "]");
|
||||||
|
|
||||||
long uploaded = coordinator.getUploaded();
|
long uploaded = coordinator.getUploaded();
|
||||||
long downloaded = coordinator.getDownloaded();
|
long downloaded = coordinator.getDownloaded();
|
||||||
long left = coordinator.getLeft();
|
long left = coordinator.getLeft();
|
||||||
@ -203,7 +208,7 @@ public class TrackerClient extends Thread
|
|||||||
+ "?info_hash=" + infoHash
|
+ "?info_hash=" + infoHash
|
||||||
+ "&peer_id=" + peerID
|
+ "&peer_id=" + peerID
|
||||||
+ "&port=" + port
|
+ "&port=" + port
|
||||||
+ "&ip=" + I2PSnarkUtil.instance().getOurIPString()
|
+ "&ip=" + I2PSnarkUtil.instance().getOurIPString() + ".i2p"
|
||||||
+ "&uploaded=" + uploaded
|
+ "&uploaded=" + uploaded
|
||||||
+ "&downloaded=" + downloaded
|
+ "&downloaded=" + downloaded
|
||||||
+ "&left=" + left
|
+ "&left=" + left
|
||||||
|
@ -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
|
2005-12-09 zzz
|
||||||
* Create different strategies for exploratory tunnels (which are difficult
|
* Create different strategies for exploratory tunnels (which are difficult
|
||||||
|
Reference in New Issue
Block a user