10 Commits

Author SHA1 Message Date
zzz
22cf9e06ff 0.15.0 2017-03-11 18:23:14 +00:00
zzz
758c0865dc clean up warnings 2017-03-07 15:33:33 +00:00
zzz
ab14737fd1 For webapp also:
Pull in override.properties for bootclasspath
Bump to java 1.6
2016-08-14 15:38:58 +00:00
zzz
dd0d7ba6c9 Pull in override.properties for bootclasspath
Bump to java 1.6
2016-08-14 15:33:23 +00:00
zzz
d3ccdb5970 increase limits, set tag options 2016-06-13 16:34:35 +00:00
zzz
404ec7d720 update for 0.9.17 2016-06-13 16:34:18 +00:00
zzz
fa37064834 0.14.0 2015-05-28 13:00:07 +00:00
zzz
7cc2d97825 Remove use of deprecated SimpleScheduler
Remove static structures
Use RandomIterator for efficiency
untested
2015-04-16 22:33:50 +00:00
zzz
9ffef703b5 Increase startup delay, so it's after the eepsite Jetty,
so it doesn't create the static RolloverFileOutputStream Timer thread,
so PluginStarter doesn't think it's running after it stops.
2014-11-29 14:05:07 +00:00
zzz
5239dfb768 fix NPE on missing announce parameters 2014-11-26 20:52:58 +00:00
14 changed files with 362 additions and 127 deletions

View File

@ -1,3 +1,19 @@
0.15.0
2017-03-11
Increase default limits, set I2CP tag options
Update eepsite configuration for Jetty 9 (I2P 0.9.30)
0.14.0
2015-05-28
Remove use of deprecated SimpleScheduler (ticket #1523)
Remove static structures
Use RandomIterator for efficiency
0.13.0
2014-11-29
Fix NPE on missing announce parameters
Increase startup delay
0.12.0
2014-11-13
Fix parameter decoding for scrape also

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<project basedir="." default="all" name="zzzot">
<property file="override.properties"/>
<target name="all" depends="clean,plugin" />
@ -15,7 +16,7 @@
<delete dir="plugin/eepsite/docroot/torrents/" />
<!-- get version number -->
<buildnumber file="scripts/build.number" />
<property name="release.number" value="0.12.0" />
<property name="release.number" value="0.15.0" />
<!-- make the update xpi2p -->
<!-- this contains everything except i2ptunnel.config -->

View File

@ -2,7 +2,7 @@ clientApp.0.main=net.i2p.zzzot.ZzzOTController
clientApp.0.name=ZzzOT
clientApp.0.args=-d $PLUGIN start
clientApp.0.stopargs=-d $PLUGIN stop
clientApp.0.delay=15
clientApp.0.delay=40
clientApp.0.startOnLoad=true
# we also use i2p.jar and i2ptunnel.jar, they are in the standard router classpath
clientApp.0.classpath=$PLUGIN/lib/zzzot.jar,$I2P/lib/i2psnark.jar

View File

@ -15,10 +15,10 @@
<!-- * threads: Raise maximumPoolSize in the ThreadPool section -->
<!-- if you have a high-traffic site and get a lot of warnings. -->
<!-- -->
<!-- I2P uses Jetty 7. If you need web server features not found -->
<!-- in Jetty 7, you may install and run Jetty 7 or 8 in a different JVM -->
<!-- I2P uses Jetty 9. If you need web server features not found -->
<!-- in I2P's Jetty 9, you may install and run Jetty 9 in a different JVM -->
<!-- or run any other web server such as Apache. If you do run another web -->
<!-- server instead, be sure and disable the Jetty 6 server for your -->
<!-- server instead, be sure and disable the Jetty 9 server for your -->
<!-- eepsite on http://127.0.0.1:7657/configclients.jsp . -->
<!-- -->
<!-- Jetty now uses the I2P logging system rather than wrapper.log. -->
@ -42,18 +42,18 @@
<!-- =========================================================== -->
<!-- Server Thread Pool -->
<!-- =========================================================== -->
<Set name="ThreadPool">
<!-- PICK ONE -->
<Arg>
<!--
Recommended.
Requests above the maxThreads + queue_size will be rejected and logged.
ref:
https://wiki.eclipse.org/Jetty/Howto/High_Load
http://trac.i2p2.i2p/ticket/1395
-->
<New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
<Arg type="int">20</Arg> <!-- maxThreads, overridden below -->
<Arg type="int">3</Arg> <!-- minThreads, overridden below -->
<Arg type="int">60000</Arg> <!-- maxIdleTimeMs, overridden below -->
<Arg>
<New class="java.util.concurrent.LinkedBlockingQueue">
<Arg type="int">50</Arg>
@ -61,43 +61,11 @@
</Arg>
<Set name="minThreads">4</Set>
<Set name="maxThreads">20</Set>
<Set name="maxIdleTimeMs">60000</Set>
<Set name="idleTimeout">60000</Set>
<Set name="daemon">true</Set>
<Set name="name">Zzzot Jetty</Set>
</New>
<!-- Optional Java 5 bounded threadpool with job queue
Requests above the max will be rejected and logged.
High-traffic sites should increase maximumPoolSize.
Args are:
corePoolSize (should be at least 3)
maximumPoolSize
keepAliveTime (milliseconds)
timeout (TimeUnit)
queue (BlockingQueue)
Not recommended.
ref:
http://trac.i2p2.i2p/ticket/1395
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html
-->
<!--
<New class="org.eclipse.jetty.util.thread.ExecutorThreadPool">
<Arg type="int">3</Arg>
<Arg type="int">20</Arg>
<Arg type="long">60000</Arg>
<Arg>
<Call class="java.util.concurrent.TimeUnit" name="valueOf" >
<Arg>MILLISECONDS</Arg>
</Call>
</Arg>
<Arg>
<New class="java.util.concurrent.SynchronousQueue" />
</Arg>
</New>
-->
</Set>
@ -116,37 +84,30 @@
-->
<Call name="addConnector">
<Arg>
<New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
<Set name="host">127.0.0.1</Set>
<Set name="port">7662</Set>
<Set name="maxIdleTime">60000</Set>
<Set name="Acceptors">1</Set>
<Set name="statsOn">false</Set>
<Set name="confidentialPort">8443</Set>
<Set name="lowResourcesConnections">5000</Set>
<Set name="lowResourcesMaxIdleTime">5000</Set>
<Set name="useDirectBuffers">false</Set>
</New>
</Arg>
</Call>
<!-- Recommended to use this connector on Java 5, as
Jetty 6 and Java 5 NIO don't play well together.
-->
<!--
<Call name="addConnector">
<New class="org.eclipse.jetty.server.ServerConnector">
<Arg><Ref id="Server" /></Arg>
<Arg type="int">1</Arg> <!-- number of acceptors -->
<Arg type="int">0</Arg> <!-- default number of selectors -->
<Arg>
<New class="org.eclipse.jetty.server.bio.SocketConnector">
<Array type="org.eclipse.jetty.server.ConnectionFactory"> <!-- varargs so we need an array -->
<Item>
<New class="org.eclipse.jetty.server.HttpConnectionFactory">
<Arg>
<New class="org.eclipse.jetty.server.HttpConfiguration">
<Set name="sendServerVersion">false</Set>
<Set name="sendDateHeader">true</Set>
</New>
</Arg>
</New>
</Item>
</Array>
</Arg>
<Set name="host">127.0.0.1</Set>
<Set name="port">7662</Set>
<Set name="maxIdleTime">60000</Set>
<Set name="Acceptors">1</Set>
<Set name="statsOn">false</Set>
<Set name="confidentialPort">8443</Set>
<Set name="idleTimeout">600000</Set>
</New>
</Arg>
</Call>
-->
<!-- =========================================================== -->
<!-- Set up global session ID manager -->
@ -301,7 +262,7 @@
<Ref id="DeploymentManager">
<Call name="addAppProvider">
<Arg>
<New class="org.eclipse.jetty.deploy.providers.ContextProvider">
<New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
<Set name="monitoredDirName">$PLUGIN/contexts</Set>
<Set name="scanInterval">120</Set>
</New>
@ -381,8 +342,6 @@
<!-- extra options -->
<!-- =========================================================== -->
<Set name="stopAtShutdown">true</Set>
<Set name="sendServerVersion">false</Set>
<Set name="sendDateHeader">true</Set>
<Set name="gracefulShutdown">1000</Set>
<Set name="stopTimeout">1000</Set>
</Configure>

View File

@ -2,27 +2,29 @@ tunnel.0.description=ZzzOT
tunnel.0.i2cpHost=127.0.0.1
tunnel.0.i2cpPort=7654
tunnel.0.name=zzzot
tunnel.0.option.crypto.lowTagThreshold=4
tunnel.0.option.crypto.tagsToSend=10
tunnel.0.option.i2cp.enableAccessList=false
tunnel.0.option.i2cp.encryptLeaseSet=false
tunnel.0.option.i2cp.reduceIdleTime=1200000
tunnel.0.option.i2cp.reduceOnIdle=true
tunnel.0.option.i2cp.reduceQuantity=1
tunnel.0.option.i2p.streaming.connectDelay=0
tunnel.0.option.i2p.streaming.maxConcurrentStreams=40
tunnel.0.option.i2p.streaming.maxConnsPerHour=100
tunnel.0.option.i2p.streaming.maxConnsPerMinute=10
tunnel.0.option.i2p.streaming.maxTotalConnsPerHour=2500
tunnel.0.option.i2p.streaming.maxTotalConnsPerMinute=60
tunnel.0.option.i2p.streaming.maxConcurrentStreams=80
tunnel.0.option.i2p.streaming.maxConnsPerHour=300
tunnel.0.option.i2p.streaming.maxConnsPerMinute=20
tunnel.0.option.i2p.streaming.maxTotalConnsPerHour=50000
tunnel.0.option.i2p.streaming.maxTotalConnsPerMinute=2000
tunnel.0.option.inbound.backupQuantity=0
tunnel.0.option.inbound.length=3
tunnel.0.option.inbound.lengthVariance=0
tunnel.0.option.inbound.nickname=ZzzOT
tunnel.0.option.inbound.quantity=2
tunnel.0.option.inbound.quantity=3
tunnel.0.option.outbound.backupQuantity=0
tunnel.0.option.outbound.length=3
tunnel.0.option.outbound.lengthVariance=0
tunnel.0.option.outbound.nickname=ZzzOT
tunnel.0.option.outbound.quantity=2
tunnel.0.option.outbound.quantity=3
tunnel.0.privKeyFile=plugins/zzzot/eepPriv.dat
tunnel.0.startOnLoad=true
tunnel.0.targetHost=127.0.0.1

View File

@ -8,6 +8,5 @@ updateURL=http://stats.i2p/i2p/plugins/zzzot-update.xpi2p
updateURL.su3=http://stats.i2p/i2p/plugins/zzzot-update.su3
websiteURL=http://zzz.i2p/forums/16
license=Apache 2.0
min-jetty-version=7
max-jetty-version=8.9999
min-i2p-version=0.9.9
min-jetty-version=9
min-i2p-version=0.9.29

View File

@ -25,13 +25,14 @@
</target>
<property name="javac.compilerargs" value="" />
<property name="javac.version" value="1.7" />
<target name="compile">
<mkdir dir="./build" />
<mkdir dir="./build/obj" />
<javac
srcdir="./java"
debug="true" deprecation="on" source="1.5" target="1.5"
debug="true" deprecation="on" source="${javac.version}" target="${javac.version}"
destdir="./build/obj"
includeAntRuntime="false"
classpath="${i2plib}/i2p.jar:${i2plib}/i2ptunnel.jar:${i2plib}/i2psnark.jar:${i2plib}/mstreaming.jar:${i2plib}/systray.jar:${jettylib}/org.mortbay.jetty.jar:${jettylib}/jetty-util.jar:${jettylib}/jetty-xml.jar" >
@ -66,13 +67,15 @@
<javac
debug="true"
deprecation="on"
source="1.5" target="1.5"
source="${javac.version}" target="${javac.version}"
destdir="build/war/WEB-INF/classes"
srcdir="./build/jspjava"
includes="**/*.java"
includeAntRuntime="false"
classpathref="jspcp"
failonerror="true" />
failonerror="true" >
<compilerarg line="${javac.compilerargs}" />
</javac>
<copy file="jsp/WEB-INF/web.xml" tofile="build/web.xml" />
<loadfile property="jspc.web.fragment" srcfile="build/web-fragment.xml" />

View File

@ -18,14 +18,12 @@ package net.i2p.zzzot;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
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.
@ -38,15 +36,9 @@ 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) {
public Peer(byte[] id, Destination address, ConcurrentMap<String, String> destCache) {
super(3);
if (id.length != 20)
throw new IllegalArgumentException("Bad peer ID length: " + id.length);
@ -83,10 +75,4 @@ public class Peer extends HashMap<String, Object> {
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

@ -0,0 +1,225 @@
package net.i2p.zzzot;
/*
* Modified from:
* http://www.lockergnome.com/awarberg/2007/04/22/random-iterator-in-java/
* No license, free to use
*/
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Random;
import net.i2p.util.RandomSource;
import net.i2p.util.SystemVersion;
/**
* Copied from net.i2p.router.util
*
* This is some Java code I wrote for a school project to save some time when iterating in
* random order over a part of list (until some condition becomes true):
*
* Here is a sample on how to use the code:
*
<pre>
for(Iterator<Object> iter = new RandomIterator<Object>(myObjList); iter.hasNext();){
Object o = iter.next();
if(someCondition(o) )
return o; // iteration stopped early
}
</pre>
*
* I wrote it to replace a Collection.shuffle call and this code gave us an overall increase in program execution speed of about 25%.
* As the javadoc description says, you are better off calling Collection.shuffle if you need to iterate over the entire list. But if you may stop early this class can save you some time, as it did in our case.
*
* Provides a random iteration over the given list.
*
* This effect can be achieved by using Collections.shuffle,
* which shuffles the entire collection in linear time.
*
* If the iteration process may end before all items
* are processed, this class may give a speed increase
* because the shuffling process is performed as items are requested
* rather than in the beginning.
*
* I2P changes:
*<pre>
* - Use BitSet instead of boolean[]
* - Use I2P RandomSource
* - Done check in next(), throw NSEE
* - Ensure lower and upper bounds are always clear
* - Replace unbounded loop in next(). It is now O(N) time, but now
* the iterator will tend to "clump" results and thus is not truly random.
* *** This class is not recommended for small Lists,
* *** or for iterating through a large portion of a List.
* *** Use Collections.shuffle() instead.
* - Add test code
*</pre>
*
* @since zzzot 0.14.0
*/
public class RandomIterator<E> implements Iterator<E> {
/**
* Mapping indicating which items were served (by index).
* if served[i] then the item with index i in the list
* has already been served.
*
* Note it is possible to save memory here by using
* BitSet rather than a boolean array, however it will
* increase the running time slightly.
*/
private final BitSet served;
/** The amount of items served so far */
private int servedCount = 0;
private final List<E> list;
private final int LIST_SIZE;
/**
* The random number generator has a great influence
* on the running time of this iterator.
*
* See, for instance,
* <a href="http://www.qbrundage.com/michaelb/pubs/essays/random_number_generation" title="http://www.qbrundage.com/michaelb/pubs/essays/random_number_generation" target="_blank">http://www.qbrundage.com/michaelb/pubs/e&#8230;</a>
* for some implementations, which are faster than java.util.Random.
*/
private final Random rand = RandomSource.getInstance();
/** Used to narrow the range to take random indexes from */
private int lower, upper;
private static final boolean hasAndroidBug;
static {
if (SystemVersion.isAndroid()) {
// only present on Gingerbread (API 11), but set if version check failed also
int ver = SystemVersion.getAndroidVersion();
hasAndroidBug = ver == 11 || ver == 0;
if (hasAndroidBug)
testAndroid();
} else {
hasAndroidBug = false;
}
}
public RandomIterator(List<E> list){
this.list = list;
LIST_SIZE = list.size();
served = new BitSet(LIST_SIZE);
upper = LIST_SIZE - 1;
}
public boolean hasNext() {
return servedCount < LIST_SIZE;
}
public E next() {
if (!hasNext())
throw new NoSuchElementException();
int range = upper - lower + 1;
// This has unbounded behavior, even with lower/upper
//int index;
//do {
// index = lower + rand.nextInt(range);
//} while (served.get(index));
// This tends to "clump" results, escpecially toward the end of the iteration.
// It also tends to leave the first and last few elements until the end.
int start = lower + rand.nextInt(range);
int index;
if ((start % 2) == 0) // coin flip
index = served.nextClearBit(start);
else
index = previousClearBit(start);
if (index < 0)
throw new NoSuchElementException("shouldn't happen");
servedCount++;
served.set(index);
// check if the range from which random values
// are taken can be reduced
// I2P - ensure lower and upper are always clear
if (hasNext()) {
if (index == lower)
// workaround for Android ICS bug - see below
lower = hasAndroidBug ? nextClearBit(index) : served.nextClearBit(index);
else if (index == upper)
upper = previousClearBit(index - 1);
}
return list.get(index);
}
/** just like nextClearBit() */
private int previousClearBit(int n) {
for (int i = n; i >= lower; i--) {
if (!served.get(i)) {
return i;
}
}
return -1;
}
/**
* Workaround for bug in Android (ICS only?)
* http://code.google.com/p/android/issues/detail?id=31036
* @since 0.9.2
*/
private int nextClearBit(int n) {
for (int i = n; i <= upper; i++) {
if (!served.get(i)) {
return i;
}
}
return -1;
}
/**
* @throws UnsupportedOperationException always
*/
public void remove() {
throw new UnsupportedOperationException();
}
/****
public static void main(String[] args) {
testAndroid();
test(0);
test(1);
test(2);
test(1000);
}
private static void test(int n) {
System.out.println("testing with " + n);
List<Integer> l = new ArrayList<Integer>(n);
for (int i = 0; i < n; i++) {
l.add(Integer.valueOf(i));
}
for (Iterator<Integer> iter = new RandomIterator<Integer>(l); iter.hasNext(); ) {
System.out.println(iter.next().toString());
}
}
****/
/**
* Test case from android ticket above
* @since 0.9.2
*/
private static void testAndroid() {
System.out.println("Checking for Android BitSet bug");
BitSet theBitSet = new BitSet(864);
for (int exp =0; exp < 864; exp++) {
int act = theBitSet.nextClearBit(0);
if (exp != act) {
System.err.println(String.format("Test failed for: exp=%d, act=%d", exp, act));
System.err.println("Android BitSet bug detected, workaround implemented!");
return;
}
theBitSet.set(exp);
}
System.err.println("Android BitSet bug NOT detected, no workaround needed!");
}
}

View File

@ -18,6 +18,8 @@ package net.i2p.zzzot;
import java.util.Iterator;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import net.i2p.I2PAppContext;
import net.i2p.util.SimpleTimer2;
@ -29,10 +31,12 @@ class ZzzOT {
private final Torrents _torrents;
private final Cleaner _cleaner;
private final ConcurrentHashMap<String, String> _destCache = new ConcurrentHashMap<String, String>();
private final long EXPIRE_TIME;
private static final String PROP_INTERVAL = "interval";
private static final long CLEAN_TIME = 4*60*1000;
private static final long DEST_CACHE_CLEAN_TIME = 3*60*60*1000;
private static final int DEFAULT_INTERVAL = 27*60;
private static final int MIN_INTERVAL = 15*60;
private static final int MAX_INTERVAL = 6*60*60;
@ -58,6 +62,11 @@ class ZzzOT {
return _torrents;
}
/** @since 0.9.14 */
ConcurrentHashMap<String, String> getDestCache() {
return _destCache;
}
void start() {
_cleaner.forceReschedule(CLEAN_TIME);
}
@ -65,10 +74,13 @@ class ZzzOT {
void stop() {
_cleaner.cancel();
_torrents.clear();
_destCache.clear();
}
private class Cleaner extends SimpleTimer2.TimedEvent {
private final AtomicInteger _runCount = new AtomicInteger();
/** must schedule later */
public Cleaner(I2PAppContext ctx) {
super(ctx.simpleTimer2());
@ -89,6 +101,9 @@ class ZzzOT {
if (recent <= 0)
iter.remove();
}
if (_runCount.incrementAndGet() % (DEST_CACHE_CLEAN_TIME / CLEAN_TIME) == 0) {
_destCache.clear();
}
schedule(CLEAN_TIME);
}
}

View File

@ -21,6 +21,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ConcurrentMap;
import net.i2p.CoreVersion;
import net.i2p.I2PAppContext;
@ -69,7 +70,7 @@ public class ZzzOTController implements ClientApp {
private static final String NAME = "ZzzOT";
private static final String CONFIG_FILE = "zzzot.config";
private static final String BACKUP_SUFFIX = ".jetty6";
private static final String BACKUP_SUFFIX = ".jetty8";
private static final String[] xmlFiles = {
"jetty.xml", "contexts/base-context.xml", "contexts/cgi-context.xml",
"etc/realm.properties", "etc/webdefault.xml" };
@ -119,6 +120,22 @@ public class ZzzOTController implements ClientApp {
return ctrlr._zzzot.getTorrents();
}
/**
* @return null if not running
* @since 0.9.14
*/
public static ConcurrentMap<String, String> getDestCache() {
ClientAppManager mgr = I2PAppContext.getGlobalContext().clientAppManager();
if (mgr == null)
return null;
ClientApp z = mgr.getRegisteredApp(NAME);
if (z == null)
return null;
ZzzOTController ctrlr = (ZzzOTController) z;
return ctrlr._zzzot.getDestCache();
}
/**
* @param args ignored
*/
@ -211,11 +228,8 @@ public class ZzzOTController implements ClientApp {
if (_tunnel == null)
return;
try {
// destroyTunnel() not available until 0.9.17, but we put 0.9.16 here for now
// so we get testing in 0.9.16-6 or later dev builds.
// No access to RouterVersion here.
// TODO change to 0.9.17
if (VersionComparator.comp(CoreVersion.VERSION, "0.9.16") >= 0) {
// destroyTunnel() not available until 0.9.17
if (VersionComparator.comp(CoreVersion.VERSION, "0.9.17") >= 0) {
try {
_tunnel.destroyTunnel();
} catch (Throwable t) {
@ -266,10 +280,10 @@ public class ZzzOTController implements ClientApp {
* @since 0.10 (Jetty 7)
*/
private static boolean shouldMigrate(File f) {
String xml = FileUtil.readTextFile(f.getAbsolutePath(), 100, true);
String xml = FileUtil.readTextFile(f.getAbsolutePath(), 400, true);
if (xml == null)
return true;
return xml.contains("class=\"org.mortbay.jetty.Server\"");
return xml.contains("class=\"org.eclipse.jetty.server.nio.SelectChannelConnector\"");
}
/**

View File

@ -1,4 +1,4 @@
<%@page import="java.io.ByteArrayInputStream,java.util.ArrayList,java.util.Collections,java.util.List,java.util.Map,java.util.HashMap,net.i2p.data.Base64,net.i2p.data.Destination,net.i2p.zzzot.*,org.klomp.snark.bencode.BEncoder" %><%
<%@page import="java.io.ByteArrayInputStream,java.util.ArrayList,java.util.Collections,java.util.List,java.util.Map,java.util.HashMap,java.util.concurrent.ConcurrentMap,net.i2p.data.Base64,net.i2p.data.Destination,net.i2p.zzzot.*,org.klomp.snark.bencode.BEncoder" %><%
/*
* Above one-liner is so there is no whitespace -> IllegalStateException
@ -64,7 +64,8 @@
if (xff != null || xfs != null) {
fail = true;
msg = "Non-I2P access denied";
response.setStatus(403, msg);
//response.setStatus(403, msg);
response.setStatus(403);
}
if (info_hash == null && !fail) {
@ -72,7 +73,7 @@
msg = "no info hash";
}
if (info_hash.length() != 20 && !fail) {
if (!fail && info_hash.length() != 20) {
fail = true;
msg = "bad info hash length " + info_hash.length();
}
@ -87,7 +88,7 @@
msg = "no peer id";
}
if (peer_id.length() != 20 && !fail) {
if (!fail && peer_id.length() != 20) {
fail = true;
msg = "bad peer id length " + peer_id.length();
}
@ -177,7 +178,7 @@
} catch (NumberFormatException nfe) {};
}
Map<String, Object> m = new HashMap(8);
Map<String, Object> m = new HashMap<String, Object>(8);
if (fail) {
m.put("failure reason", msg);
} else if ("stopped".equals(event)) {
@ -197,7 +198,8 @@
// fixme same peer id, different dest
Peer p = peers.get(pid);
if (p == null) {
p = new Peer(pid.getData(), d);
ConcurrentMap<String, String> destCache = ZzzOTController.getDestCache();
p = new Peer(pid.getData(), d, destCache);
// don't add if spoofed
if (matchIP) {
Peer p2 = peers.putIfAbsent(pid, p);
@ -218,12 +220,21 @@
// snark < 0.7.13 always wants a list
m.put("peers", java.util.Collections.EMPTY_LIST);
} else {
List<Peer> peerlist = new ArrayList(peers.values());
List<Peer> peerlist = new ArrayList<Peer>(peers.values());
peerlist.remove(p); // them
if (want < size - 1) {
if (size > 150) {
// If size is huge, use random iterator for efficiency
List<Peer> rv = new ArrayList<Peer>(size);
for (RandomIterator<Peer> iter = new RandomIterator<Peer>(peerlist); iter.hasNext(); ) {
rv.add(iter.next());
}
peerlist = rv;
} else {
Collections.shuffle(peerlist);
peerlist = peerlist.subList(0, want);
}
}
if (compact) {
// old experimental way - list of hashes
//List<String> peerhashes = new ArrayList(peerlist.size());

View File

@ -45,7 +45,8 @@
if (xff != null || xfs != null) {
fail = true;
msg = "Non-I2P access denied";
response.setStatus(403, msg);
//response.setStatus(403, msg);
response.setStatus(403);
}
boolean all = info_hash == null;
@ -67,21 +68,21 @@
}
// build 3-level dictionary
Map<String, Object> m = new HashMap(4);
Map<String, Object> m = new HashMap<String, Object>(4);
if (fail) {
m.put("failure reason", msg);
} else {
List<InfoHash> ihList = new ArrayList();
List<InfoHash> ihList = new ArrayList<InfoHash>();
if (all)
ihList.addAll(torrents.keySet());
else
ihList.add(ih);
Map<String, Map> files = new HashMap();
Map<String, Map> files = new HashMap<String, Map>();
for (InfoHash ihash : ihList) {
Peers peers = torrents.get(ihash);
if (peers == null)
continue;
Map<String, Object> dict = new HashMap();
Map<String, Object> dict = new HashMap<String, Object>();
int size = peers.size();
int seeds = peers.countSeeds();
dict.put("complete", Integer.valueOf(seeds));

View File

@ -40,7 +40,8 @@
if (xff != null || xfs != null) {
String msg = "Non-I2P access denied";
response.setStatus(403, msg);
//response.setStatus(403, msg);
response.setStatus(403);
out.println(msg);
} else if (req == null) {
// probe
@ -63,7 +64,8 @@
// all the peers
Torrents torrents = ZzzOTController.getTorrents();
if (torrents == null) {
response.setStatus(503, "Down");
//response.setStatus(503, "Down");
response.setStatus(503);
return;
}
for (InfoHash ihash : torrents.keySet()) {
@ -92,7 +94,8 @@
}
} else {
// error code
response.setStatus(406, "Bad request");
//response.setStatus(406, "Bad request");
response.setStatus(406);
out.println("SC_NOT_ACCEPTABLE");
}