4 Commits

Author SHA1 Message Date
zzz
48687daccc 0.4:
compact request/response support - may not be final format
Fix NPE if no ip parameter
2010-07-09 16:31:24 +00:00
zzz
66667de240 0.3: verify dest 2010-04-13 17:41:24 +00:00
zzz
eda5699f38 add xfs check 2010-04-12 22:01:50 +00:00
zzz
902377b92a 0.2:
cache b64 dest strings
help typo fix (thx duck)
lots of seedless fixes
build cleanups
2010-03-24 03:01:38 +00:00
8 changed files with 102 additions and 44 deletions

View File

@ -11,7 +11,7 @@
<delete file="plugin/i2ptunnel.config" />
<!-- get version number -->
<buildnumber file="scripts/build.number" />
<property name="release.number" value="0.1" />
<property name="release.number" value="0.4" />
<!-- make the update xpi2p -->
<!-- this contains everything except i2ptunnel.config -->

View File

@ -8,7 +8,7 @@ A new eepsite tunnel and Jetty server have been started for your open tracker.
This link is also at the top of your router console when ZzzOT is running.
<p>Report bugs or add comments on
<a href="htp://zzz.i2p//forums/16">the plugin forum on zzz.i2p</a>.
<a href="http://zzz.i2p//forums/16">the plugin forum on zzz.i2p</a>.
<h3>Eepsite Key and Helpful Hints for I2P</h3>

View File

@ -145,6 +145,10 @@
<Arg>/Seedless/index.jsp</Arg>
<Arg>/tracker/seedless.jsp</Arg>
</Call>
<Call name="addForward">
<Arg>/Seedless/seedless</Arg>
<Arg>/tracker/seedless.jsp</Arg>
</Call>
</New>
</Arg>
</Call>

View File

@ -10,7 +10,6 @@
<pathelement location="${i2plib}/i2p.jar" />
<pathelement location="${i2plib}/i2ptunnel.jar" />
<pathelement location="${i2plib}/i2psnark.jar" />
<pathelement location="${i2plib}/routerconsole.jar" />
<pathelement location="${jettylib}/ant.jar"/>
<pathelement location="${jettylib}/org.mortbay.jetty.jar"/>
<pathelement location="${jettylib}/jasper-compiler.jar" />
@ -24,27 +23,10 @@
<target name="build" depends="jar, war" />
<target name="builddep">
</target>
<condition property="depend.available">
<typefound name="depend" />
</condition>
<target name="depend" if="depend.available">
<depend
cache="build"
srcdir="./src"
destdir="./build/obj" >
<!-- Depend on classes instead of jars where available -->
<classpath>
<pathelement location="../../../core/java/build/obj" />
<pathelement location="../../ministreaming/java/build/obj" />
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
</classpath>
</depend>
</target>
<property name="javac.compilerargs" value="" />
<target name="compile" depends="depend">
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac

View File

@ -18,8 +18,14 @@ package net.i2p.zzzot;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import net.i2p.crypto.SHA256Generator;
import net.i2p.data.Base64;
import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
/*
* A single peer for a single torrent.
@ -32,15 +38,26 @@ public class Peer extends HashMap<String, Object> {
private long lastSeen;
private long bytesLeft;
private static final ConcurrentHashMap<String, String> destCache = new ConcurrentHashMap();
private static final Integer PORT = Integer.valueOf(6881);
private static final long CLEAN_TIME = 3*60*60*1000;
static {
SimpleScheduler.getInstance().addPeriodicEvent(new Cleaner(), CLEAN_TIME);
}
public Peer(byte[] id, Destination address) {
super(3);
if (id.length != 20)
throw new IllegalArgumentException("Bad peer ID length: " + id.length);
put("peer id", id);
put("ip", address.toBase64() + ".i2p");
put("port", PORT);
// cache the 520-byte address strings
String dest = address.toBase64() + ".i2p";
String oldDest = destCache.putIfAbsent(dest, dest);
if (oldDest != null)
dest = oldDest;
put("ip", dest);
}
public void setLeft(long l) {
@ -55,4 +72,21 @@ public class Peer extends HashMap<String, Object> {
public long lastSeen() {
return lastSeen;
}
/** convert b64.i2p to a Hash, then to a binary string */
/* or should we just store it in the constructor? cache it? */
public String getHash() {
String ip = (String) get("ip");
byte[] b = Base64.decode(ip.substring(0, ip.length() - 4));
Hash h = SHA256Generator.getInstance().calculateHash(b);
try {
return new String(h.getData(), "ISO-8859-1");
} catch (UnsupportedEncodingException uee) { return null; }
}
private static class Cleaner implements SimpleTimer.TimedEvent {
public void timeReached() {
destCache.clear();
}
}
}

View File

@ -28,6 +28,8 @@
// would be nice to make these configurable
final int MAX_RESPONSES = 25;
final int INTERVAL = 27*60;
final boolean ALLOW_IP_MISMATCH = false;
final boolean ALLOW_COMPACT_RESPONSE = true;
// so the chars will turn into bytes correctly
request.setCharacterEncoding("ISO-8859-1");
@ -47,14 +49,16 @@
String event = request.getParameter("event");
String ip = request.getParameter("ip");
String numwant = request.getParameter("numwant");
// ignored, use someday to enforce destination
String him = request.getHeader("X-I2P-DestB32");
boolean compact = ALLOW_COMPACT_RESPONSE && request.getParameter("compact") != null;
// use to enforce destination
String him = request.getHeader("X-I2P-DestB64");
String xff = request.getHeader("X-Forwarded-For");
String xfs = request.getHeader("X-Forwarded-Server");
boolean fail = false;
String msg = "bad announce";
if (xff != null) {
if (xff != null || xfs != null) {
fail = true;
msg = "Non-I2P access denied";
response.setStatus(403, msg);
@ -134,6 +138,14 @@
want = 0;
} catch (NumberFormatException nfe) {};
// spoof check
// if him == null, we are not using the I2P HTTP server tunnel, or something is wrong
boolean matchIP = ALLOW_IP_MISMATCH || him == null || ip == null || ip.equals(him);
if (want <= 0 && (!matchIP) && !fail) {
fail = true;
msg = "ip mismatch";
}
long left = 0;
if (!"completed".equals(event)) {
try {
@ -149,7 +161,7 @@
m.put("failure reason", msg);
} else if ("stopped".equals(event)) {
Peers peers = torrents.get(ih);
if (peers != null)
if (matchIP && peers != null)
peers.remove(pid);
m.put("interval", Integer.valueOf(INTERVAL));
} else {
@ -165,11 +177,16 @@
Peer p = peers.get(pid);
if (p == null) {
p = new Peer(pid.getData(), d);
Peer p2 = peers.putIfAbsent(pid, p);
if (p2 != null)
p = p2;
// don't add if spoofed
if (matchIP) {
Peer p2 = peers.putIfAbsent(pid, p);
if (p2 != null)
p = p2;
}
}
p.setLeft(left);
// don't update if spoofed
if (matchIP)
p.setLeft(left);
m.put("interval", Integer.valueOf(INTERVAL));
int size = peers.size();
@ -184,7 +201,14 @@
peerlist.remove(p); // them
if (want < size - 1) {
Collections.shuffle(peerlist);
m.put("peers", peerlist.subList(0, want));
peerlist = peerlist.subList(0, want);
}
if (compact) {
List<String> peerhashes = new ArrayList(peerlist.size());
for (Peer pe : peerlist) {
peerhashes.add(pe.getHash());
}
m.put("peers", peerhashes);
} else {
m.put("peers", peerlist);
}

View File

@ -33,11 +33,12 @@
response.setHeader("Pragma", "no-cache");
String info_hash = request.getParameter("info_hash");
String xff = request.getHeader("X-Forwarded-For");
String xfs = request.getHeader("X-Forwarded-Server");
boolean fail = false;
String msg = "bad";
if (xff != null) {
if (xff != null || xfs != null) {
fail = true;
msg = "Non-I2P access denied";
response.setStatus(403, msg);

View File

@ -1,4 +1,4 @@
<%@page import="net.i2p.crypto.SHA256Generator" %><%@page import="net.i2p.data.Base32" %><%@page import="net.i2p.data.Base64" %><%@page import="net.i2p.zzzot.*" %><%
<%@page import="net.i2p.crypto.SHA256Generator" %><%@page import="net.i2p.data.Base32" %><%@page import="net.i2p.data.Base64" %><%@page import="net.i2p.data.DataHelper" %><%@page import="net.i2p.zzzot.*" %><%
/*
* Copyright 2010 zzz (zzz@mail.i2p)
@ -18,10 +18,17 @@
*/
String req = request.getHeader("X-Seedless");
// extension for ease of eepget and browser
if (req == null)
req = request.getParameter("X-Seedless");
// we should really put in our own b32
String me = request.getHeader("Host");
if (me == null)
me = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.b32.i2p";
// unused, we don't accept announces
String him = request.getHeader("X-I2P-DestB32");
String xff = request.getHeader("X-Forwarded-For");
String xfs = request.getHeader("X-Forwarded-Server");
response.setContentType("text/plain");
response.setHeader("X-Seedless", me);
@ -29,18 +36,23 @@
final int US_MINUTES = 360;
final int PEER_MINUTES = 60;
if (xff != null) {
if (xff != null || xfs != null) {
String msg = "Non-I2P access denied";
response.setStatus(403, msg);
out.println(msg);
} else if (req == null) {
out.println("seedless server");
} else if (req.startsWith("announce ")) {
out.println("");
} else if (req.startsWith("locate ") && me != null) {
// probe
out.println("tracker " + US_MINUTES);
out.println("eepsite " + US_MINUTES);
out.println("seedless " + US_MINUTES);
} else if (req.startsWith("announce")) {
out.println("thanks");
} else if (req.startsWith("locate")) {
// ignore the search string, if any, in the request
// us
out.println(Base64.encode(me + ' ' + US_MINUTES + " bt-tracker"));
out.println(Base64.encode(me + ' ' + US_MINUTES + " tracker"));
out.println(Base64.encode(me + ' ' + US_MINUTES + " seedless"));
out.println(Base64.encode(me + ' ' + US_MINUTES + " eepsite"));
// all the peers
Torrents torrents = ZzzOTController.getTorrents();
for (InfoHash ihash : torrents.keySet()) {
@ -59,16 +71,17 @@
role = " bt-seed";
else
role = " bt-leech";
// spg wants UTF-8 but all we have is binary data, sorry
String ihs = new String(ihash.getData(), "ISO-8859-1");
String ids = new String((byte[])p.get("peer id"), "ISO-8859-1");
// spg wants UTF-8 but all we have is binary data, so hex it
String ihs = DataHelper.toHexString(ihash.getData());
String ids = DataHelper.toHexString((byte[])p.get("peer id"));
out.println(Base64.encode(b32 + PEER_MINUTES + role +
" info_hash=" + ihs +
" peer_id=" + ids));
";peer_id=" + ids));
}
}
} else {
out.println("2");
// error code
out.println("SC_NOT_ACCEPTABLE");
}
%>