Compare commits
10 Commits
zzzot-0.12
...
zzzot-0.15
Author | SHA1 | Date | |
---|---|---|---|
22cf9e06ff | |||
758c0865dc | |||
ab14737fd1 | |||
dd0d7ba6c9 | |||
d3ccdb5970 | |||
404ec7d720 | |||
fa37064834 | |||
7cc2d97825 | |||
9ffef703b5 | |||
5239dfb768 |
16
CHANGES.txt
16
CHANGES.txt
@ -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
|
0.12.0
|
||||||
2014-11-13
|
2014-11-13
|
||||||
Fix parameter decoding for scrape also
|
Fix parameter decoding for scrape also
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
<project basedir="." default="all" name="zzzot">
|
<project basedir="." default="all" name="zzzot">
|
||||||
|
<property file="override.properties"/>
|
||||||
|
|
||||||
<target name="all" depends="clean,plugin" />
|
<target name="all" depends="clean,plugin" />
|
||||||
|
|
||||||
@ -15,7 +16,7 @@
|
|||||||
<delete dir="plugin/eepsite/docroot/torrents/" />
|
<delete dir="plugin/eepsite/docroot/torrents/" />
|
||||||
<!-- get version number -->
|
<!-- get version number -->
|
||||||
<buildnumber file="scripts/build.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 -->
|
<!-- make the update xpi2p -->
|
||||||
<!-- this contains everything except i2ptunnel.config -->
|
<!-- this contains everything except i2ptunnel.config -->
|
||||||
|
@ -2,7 +2,7 @@ clientApp.0.main=net.i2p.zzzot.ZzzOTController
|
|||||||
clientApp.0.name=ZzzOT
|
clientApp.0.name=ZzzOT
|
||||||
clientApp.0.args=-d $PLUGIN start
|
clientApp.0.args=-d $PLUGIN start
|
||||||
clientApp.0.stopargs=-d $PLUGIN stop
|
clientApp.0.stopargs=-d $PLUGIN stop
|
||||||
clientApp.0.delay=15
|
clientApp.0.delay=40
|
||||||
clientApp.0.startOnLoad=true
|
clientApp.0.startOnLoad=true
|
||||||
# we also use i2p.jar and i2ptunnel.jar, they are in the standard router classpath
|
# 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
|
clientApp.0.classpath=$PLUGIN/lib/zzzot.jar,$I2P/lib/i2psnark.jar
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
<!-- * threads: Raise maximumPoolSize in the ThreadPool section -->
|
<!-- * threads: Raise maximumPoolSize in the ThreadPool section -->
|
||||||
<!-- if you have a high-traffic site and get a lot of warnings. -->
|
<!-- 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 -->
|
<!-- I2P uses Jetty 9. If you need web server features not found -->
|
||||||
<!-- in Jetty 7, you may install and run Jetty 7 or 8 in a different JVM -->
|
<!-- 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 -->
|
<!-- 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 . -->
|
<!-- eepsite on http://127.0.0.1:7657/configclients.jsp . -->
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<!-- Jetty now uses the I2P logging system rather than wrapper.log. -->
|
<!-- Jetty now uses the I2P logging system rather than wrapper.log. -->
|
||||||
@ -42,18 +42,18 @@
|
|||||||
<!-- =========================================================== -->
|
<!-- =========================================================== -->
|
||||||
<!-- Server Thread Pool -->
|
<!-- Server Thread Pool -->
|
||||||
<!-- =========================================================== -->
|
<!-- =========================================================== -->
|
||||||
<Set name="ThreadPool">
|
<Arg>
|
||||||
|
|
||||||
<!-- PICK ONE -->
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Recommended.
|
|
||||||
Requests above the maxThreads + queue_size will be rejected and logged.
|
Requests above the maxThreads + queue_size will be rejected and logged.
|
||||||
ref:
|
ref:
|
||||||
https://wiki.eclipse.org/Jetty/Howto/High_Load
|
https://wiki.eclipse.org/Jetty/Howto/High_Load
|
||||||
http://trac.i2p2.i2p/ticket/1395
|
http://trac.i2p2.i2p/ticket/1395
|
||||||
-->
|
-->
|
||||||
<New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
|
<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>
|
<Arg>
|
||||||
<New class="java.util.concurrent.LinkedBlockingQueue">
|
<New class="java.util.concurrent.LinkedBlockingQueue">
|
||||||
<Arg type="int">50</Arg>
|
<Arg type="int">50</Arg>
|
||||||
@ -61,43 +61,11 @@
|
|||||||
</Arg>
|
</Arg>
|
||||||
<Set name="minThreads">4</Set>
|
<Set name="minThreads">4</Set>
|
||||||
<Set name="maxThreads">20</Set>
|
<Set name="maxThreads">20</Set>
|
||||||
<Set name="maxIdleTimeMs">60000</Set>
|
<Set name="idleTimeout">60000</Set>
|
||||||
<Set name="daemon">true</Set>
|
<Set name="daemon">true</Set>
|
||||||
<Set name="name">Zzzot Jetty</Set>
|
<Set name="name">Zzzot Jetty</Set>
|
||||||
</New>
|
</New>
|
||||||
|
</Arg>
|
||||||
<!-- 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,38 +84,31 @@
|
|||||||
-->
|
-->
|
||||||
<Call name="addConnector">
|
<Call name="addConnector">
|
||||||
<Arg>
|
<Arg>
|
||||||
<New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
|
<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>
|
||||||
|
<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="host">127.0.0.1</Set>
|
||||||
<Set name="port">7662</Set>
|
<Set name="port">7662</Set>
|
||||||
<Set name="maxIdleTime">60000</Set>
|
<Set name="idleTimeout">600000</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>
|
</New>
|
||||||
</Arg>
|
</Arg>
|
||||||
</Call>
|
</Call>
|
||||||
|
|
||||||
<!-- Recommended to use this connector on Java 5, as
|
|
||||||
Jetty 6 and Java 5 NIO don't play well together.
|
|
||||||
-->
|
|
||||||
<!--
|
|
||||||
<Call name="addConnector">
|
|
||||||
<Arg>
|
|
||||||
<New class="org.eclipse.jetty.server.bio.SocketConnector">
|
|
||||||
<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>
|
|
||||||
</New>
|
|
||||||
</Arg>
|
|
||||||
</Call>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- =========================================================== -->
|
<!-- =========================================================== -->
|
||||||
<!-- Set up global session ID manager -->
|
<!-- Set up global session ID manager -->
|
||||||
<!-- =========================================================== -->
|
<!-- =========================================================== -->
|
||||||
@ -301,7 +262,7 @@
|
|||||||
<Ref id="DeploymentManager">
|
<Ref id="DeploymentManager">
|
||||||
<Call name="addAppProvider">
|
<Call name="addAppProvider">
|
||||||
<Arg>
|
<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="monitoredDirName">$PLUGIN/contexts</Set>
|
||||||
<Set name="scanInterval">120</Set>
|
<Set name="scanInterval">120</Set>
|
||||||
</New>
|
</New>
|
||||||
@ -381,8 +342,6 @@
|
|||||||
<!-- extra options -->
|
<!-- extra options -->
|
||||||
<!-- =========================================================== -->
|
<!-- =========================================================== -->
|
||||||
<Set name="stopAtShutdown">true</Set>
|
<Set name="stopAtShutdown">true</Set>
|
||||||
<Set name="sendServerVersion">false</Set>
|
<Set name="stopTimeout">1000</Set>
|
||||||
<Set name="sendDateHeader">true</Set>
|
|
||||||
<Set name="gracefulShutdown">1000</Set>
|
|
||||||
|
|
||||||
</Configure>
|
</Configure>
|
||||||
|
@ -2,27 +2,29 @@ tunnel.0.description=ZzzOT
|
|||||||
tunnel.0.i2cpHost=127.0.0.1
|
tunnel.0.i2cpHost=127.0.0.1
|
||||||
tunnel.0.i2cpPort=7654
|
tunnel.0.i2cpPort=7654
|
||||||
tunnel.0.name=zzzot
|
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.enableAccessList=false
|
||||||
tunnel.0.option.i2cp.encryptLeaseSet=false
|
tunnel.0.option.i2cp.encryptLeaseSet=false
|
||||||
tunnel.0.option.i2cp.reduceIdleTime=1200000
|
tunnel.0.option.i2cp.reduceIdleTime=1200000
|
||||||
tunnel.0.option.i2cp.reduceOnIdle=true
|
tunnel.0.option.i2cp.reduceOnIdle=true
|
||||||
tunnel.0.option.i2cp.reduceQuantity=1
|
tunnel.0.option.i2cp.reduceQuantity=1
|
||||||
tunnel.0.option.i2p.streaming.connectDelay=0
|
tunnel.0.option.i2p.streaming.connectDelay=0
|
||||||
tunnel.0.option.i2p.streaming.maxConcurrentStreams=40
|
tunnel.0.option.i2p.streaming.maxConcurrentStreams=80
|
||||||
tunnel.0.option.i2p.streaming.maxConnsPerHour=100
|
tunnel.0.option.i2p.streaming.maxConnsPerHour=300
|
||||||
tunnel.0.option.i2p.streaming.maxConnsPerMinute=10
|
tunnel.0.option.i2p.streaming.maxConnsPerMinute=20
|
||||||
tunnel.0.option.i2p.streaming.maxTotalConnsPerHour=2500
|
tunnel.0.option.i2p.streaming.maxTotalConnsPerHour=50000
|
||||||
tunnel.0.option.i2p.streaming.maxTotalConnsPerMinute=60
|
tunnel.0.option.i2p.streaming.maxTotalConnsPerMinute=2000
|
||||||
tunnel.0.option.inbound.backupQuantity=0
|
tunnel.0.option.inbound.backupQuantity=0
|
||||||
tunnel.0.option.inbound.length=3
|
tunnel.0.option.inbound.length=3
|
||||||
tunnel.0.option.inbound.lengthVariance=0
|
tunnel.0.option.inbound.lengthVariance=0
|
||||||
tunnel.0.option.inbound.nickname=ZzzOT
|
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.backupQuantity=0
|
||||||
tunnel.0.option.outbound.length=3
|
tunnel.0.option.outbound.length=3
|
||||||
tunnel.0.option.outbound.lengthVariance=0
|
tunnel.0.option.outbound.lengthVariance=0
|
||||||
tunnel.0.option.outbound.nickname=ZzzOT
|
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.privKeyFile=plugins/zzzot/eepPriv.dat
|
||||||
tunnel.0.startOnLoad=true
|
tunnel.0.startOnLoad=true
|
||||||
tunnel.0.targetHost=127.0.0.1
|
tunnel.0.targetHost=127.0.0.1
|
||||||
|
@ -8,6 +8,5 @@ updateURL=http://stats.i2p/i2p/plugins/zzzot-update.xpi2p
|
|||||||
updateURL.su3=http://stats.i2p/i2p/plugins/zzzot-update.su3
|
updateURL.su3=http://stats.i2p/i2p/plugins/zzzot-update.su3
|
||||||
websiteURL=http://zzz.i2p/forums/16
|
websiteURL=http://zzz.i2p/forums/16
|
||||||
license=Apache 2.0
|
license=Apache 2.0
|
||||||
min-jetty-version=7
|
min-jetty-version=9
|
||||||
max-jetty-version=8.9999
|
min-i2p-version=0.9.29
|
||||||
min-i2p-version=0.9.9
|
|
||||||
|
@ -25,13 +25,14 @@
|
|||||||
</target>
|
</target>
|
||||||
|
|
||||||
<property name="javac.compilerargs" value="" />
|
<property name="javac.compilerargs" value="" />
|
||||||
|
<property name="javac.version" value="1.7" />
|
||||||
|
|
||||||
<target name="compile">
|
<target name="compile">
|
||||||
<mkdir dir="./build" />
|
<mkdir dir="./build" />
|
||||||
<mkdir dir="./build/obj" />
|
<mkdir dir="./build/obj" />
|
||||||
<javac
|
<javac
|
||||||
srcdir="./java"
|
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"
|
destdir="./build/obj"
|
||||||
includeAntRuntime="false"
|
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" >
|
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
|
<javac
|
||||||
debug="true"
|
debug="true"
|
||||||
deprecation="on"
|
deprecation="on"
|
||||||
source="1.5" target="1.5"
|
source="${javac.version}" target="${javac.version}"
|
||||||
destdir="build/war/WEB-INF/classes"
|
destdir="build/war/WEB-INF/classes"
|
||||||
srcdir="./build/jspjava"
|
srcdir="./build/jspjava"
|
||||||
includes="**/*.java"
|
includes="**/*.java"
|
||||||
includeAntRuntime="false"
|
includeAntRuntime="false"
|
||||||
classpathref="jspcp"
|
classpathref="jspcp"
|
||||||
failonerror="true" />
|
failonerror="true" >
|
||||||
|
<compilerarg line="${javac.compilerargs}" />
|
||||||
|
</javac>
|
||||||
|
|
||||||
<copy file="jsp/WEB-INF/web.xml" tofile="build/web.xml" />
|
<copy file="jsp/WEB-INF/web.xml" tofile="build/web.xml" />
|
||||||
<loadfile property="jspc.web.fragment" srcfile="build/web-fragment.xml" />
|
<loadfile property="jspc.web.fragment" srcfile="build/web-fragment.xml" />
|
||||||
|
@ -18,14 +18,12 @@ package net.i2p.zzzot;
|
|||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import net.i2p.crypto.SHA256Generator;
|
import net.i2p.crypto.SHA256Generator;
|
||||||
import net.i2p.data.Base64;
|
import net.i2p.data.Base64;
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
import net.i2p.data.Hash;
|
import net.i2p.data.Hash;
|
||||||
import net.i2p.util.SimpleScheduler;
|
|
||||||
import net.i2p.util.SimpleTimer;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A single peer for a single torrent.
|
* A single peer for a single torrent.
|
||||||
@ -38,15 +36,9 @@ public class Peer extends HashMap<String, Object> {
|
|||||||
|
|
||||||
private long lastSeen;
|
private long lastSeen;
|
||||||
private long bytesLeft;
|
private long bytesLeft;
|
||||||
private static final ConcurrentHashMap<String, String> destCache = new ConcurrentHashMap();
|
|
||||||
private static final Integer PORT = Integer.valueOf(6881);
|
private static final Integer PORT = Integer.valueOf(6881);
|
||||||
private static final long CLEAN_TIME = 3*60*60*1000;
|
|
||||||
|
|
||||||
static {
|
public Peer(byte[] id, Destination address, ConcurrentMap<String, String> destCache) {
|
||||||
SimpleScheduler.getInstance().addPeriodicEvent(new Cleaner(), CLEAN_TIME);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Peer(byte[] id, Destination address) {
|
|
||||||
super(3);
|
super(3);
|
||||||
if (id.length != 20)
|
if (id.length != 20)
|
||||||
throw new IllegalArgumentException("Bad peer ID length: " + id.length);
|
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");
|
return new String(h.getData(), "ISO-8859-1");
|
||||||
} catch (UnsupportedEncodingException uee) { return null; }
|
} catch (UnsupportedEncodingException uee) { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Cleaner implements SimpleTimer.TimedEvent {
|
|
||||||
public void timeReached() {
|
|
||||||
destCache.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
225
src/java/net/i2p/zzzot/RandomIterator.java
Normal file
225
src/java/net/i2p/zzzot/RandomIterator.java
Normal 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…</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!");
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,8 @@ package net.i2p.zzzot;
|
|||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.util.SimpleTimer2;
|
import net.i2p.util.SimpleTimer2;
|
||||||
@ -29,10 +31,12 @@ class ZzzOT {
|
|||||||
|
|
||||||
private final Torrents _torrents;
|
private final Torrents _torrents;
|
||||||
private final Cleaner _cleaner;
|
private final Cleaner _cleaner;
|
||||||
|
private final ConcurrentHashMap<String, String> _destCache = new ConcurrentHashMap<String, String>();
|
||||||
private final long EXPIRE_TIME;
|
private final long EXPIRE_TIME;
|
||||||
|
|
||||||
private static final String PROP_INTERVAL = "interval";
|
private static final String PROP_INTERVAL = "interval";
|
||||||
private static final long CLEAN_TIME = 4*60*1000;
|
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 DEFAULT_INTERVAL = 27*60;
|
||||||
private static final int MIN_INTERVAL = 15*60;
|
private static final int MIN_INTERVAL = 15*60;
|
||||||
private static final int MAX_INTERVAL = 6*60*60;
|
private static final int MAX_INTERVAL = 6*60*60;
|
||||||
@ -58,6 +62,11 @@ class ZzzOT {
|
|||||||
return _torrents;
|
return _torrents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 0.9.14 */
|
||||||
|
ConcurrentHashMap<String, String> getDestCache() {
|
||||||
|
return _destCache;
|
||||||
|
}
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
_cleaner.forceReschedule(CLEAN_TIME);
|
_cleaner.forceReschedule(CLEAN_TIME);
|
||||||
}
|
}
|
||||||
@ -65,10 +74,13 @@ class ZzzOT {
|
|||||||
void stop() {
|
void stop() {
|
||||||
_cleaner.cancel();
|
_cleaner.cancel();
|
||||||
_torrents.clear();
|
_torrents.clear();
|
||||||
|
_destCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Cleaner extends SimpleTimer2.TimedEvent {
|
private class Cleaner extends SimpleTimer2.TimedEvent {
|
||||||
|
|
||||||
|
private final AtomicInteger _runCount = new AtomicInteger();
|
||||||
|
|
||||||
/** must schedule later */
|
/** must schedule later */
|
||||||
public Cleaner(I2PAppContext ctx) {
|
public Cleaner(I2PAppContext ctx) {
|
||||||
super(ctx.simpleTimer2());
|
super(ctx.simpleTimer2());
|
||||||
@ -89,6 +101,9 @@ class ZzzOT {
|
|||||||
if (recent <= 0)
|
if (recent <= 0)
|
||||||
iter.remove();
|
iter.remove();
|
||||||
}
|
}
|
||||||
|
if (_runCount.incrementAndGet() % (DEST_CACHE_CLEAN_TIME / CLEAN_TIME) == 0) {
|
||||||
|
_destCache.clear();
|
||||||
|
}
|
||||||
schedule(CLEAN_TIME);
|
schedule(CLEAN_TIME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import net.i2p.CoreVersion;
|
import net.i2p.CoreVersion;
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
@ -69,7 +70,7 @@ public class ZzzOTController implements ClientApp {
|
|||||||
|
|
||||||
private static final String NAME = "ZzzOT";
|
private static final String NAME = "ZzzOT";
|
||||||
private static final String CONFIG_FILE = "zzzot.config";
|
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 = {
|
private static final String[] xmlFiles = {
|
||||||
"jetty.xml", "contexts/base-context.xml", "contexts/cgi-context.xml",
|
"jetty.xml", "contexts/base-context.xml", "contexts/cgi-context.xml",
|
||||||
"etc/realm.properties", "etc/webdefault.xml" };
|
"etc/realm.properties", "etc/webdefault.xml" };
|
||||||
@ -119,6 +120,22 @@ public class ZzzOTController implements ClientApp {
|
|||||||
return ctrlr._zzzot.getTorrents();
|
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
|
* @param args ignored
|
||||||
*/
|
*/
|
||||||
@ -211,11 +228,8 @@ public class ZzzOTController implements ClientApp {
|
|||||||
if (_tunnel == null)
|
if (_tunnel == null)
|
||||||
return;
|
return;
|
||||||
try {
|
try {
|
||||||
// destroyTunnel() not available until 0.9.17, but we put 0.9.16 here for now
|
// destroyTunnel() not available until 0.9.17
|
||||||
// so we get testing in 0.9.16-6 or later dev builds.
|
if (VersionComparator.comp(CoreVersion.VERSION, "0.9.17") >= 0) {
|
||||||
// No access to RouterVersion here.
|
|
||||||
// TODO change to 0.9.17
|
|
||||||
if (VersionComparator.comp(CoreVersion.VERSION, "0.9.16") >= 0) {
|
|
||||||
try {
|
try {
|
||||||
_tunnel.destroyTunnel();
|
_tunnel.destroyTunnel();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
@ -266,10 +280,10 @@ public class ZzzOTController implements ClientApp {
|
|||||||
* @since 0.10 (Jetty 7)
|
* @since 0.10 (Jetty 7)
|
||||||
*/
|
*/
|
||||||
private static boolean shouldMigrate(File f) {
|
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)
|
if (xml == null)
|
||||||
return true;
|
return true;
|
||||||
return xml.contains("class=\"org.mortbay.jetty.Server\"");
|
return xml.contains("class=\"org.eclipse.jetty.server.nio.SelectChannelConnector\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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
|
* Above one-liner is so there is no whitespace -> IllegalStateException
|
||||||
@ -64,7 +64,8 @@
|
|||||||
if (xff != null || xfs != null) {
|
if (xff != null || xfs != null) {
|
||||||
fail = true;
|
fail = true;
|
||||||
msg = "Non-I2P access denied";
|
msg = "Non-I2P access denied";
|
||||||
response.setStatus(403, msg);
|
//response.setStatus(403, msg);
|
||||||
|
response.setStatus(403);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info_hash == null && !fail) {
|
if (info_hash == null && !fail) {
|
||||||
@ -72,7 +73,7 @@
|
|||||||
msg = "no info hash";
|
msg = "no info hash";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info_hash.length() != 20 && !fail) {
|
if (!fail && info_hash.length() != 20) {
|
||||||
fail = true;
|
fail = true;
|
||||||
msg = "bad info hash length " + info_hash.length();
|
msg = "bad info hash length " + info_hash.length();
|
||||||
}
|
}
|
||||||
@ -87,7 +88,7 @@
|
|||||||
msg = "no peer id";
|
msg = "no peer id";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peer_id.length() != 20 && !fail) {
|
if (!fail && peer_id.length() != 20) {
|
||||||
fail = true;
|
fail = true;
|
||||||
msg = "bad peer id length " + peer_id.length();
|
msg = "bad peer id length " + peer_id.length();
|
||||||
}
|
}
|
||||||
@ -177,7 +178,7 @@
|
|||||||
} catch (NumberFormatException nfe) {};
|
} catch (NumberFormatException nfe) {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> m = new HashMap(8);
|
Map<String, Object> m = new HashMap<String, Object>(8);
|
||||||
if (fail) {
|
if (fail) {
|
||||||
m.put("failure reason", msg);
|
m.put("failure reason", msg);
|
||||||
} else if ("stopped".equals(event)) {
|
} else if ("stopped".equals(event)) {
|
||||||
@ -197,7 +198,8 @@
|
|||||||
// fixme same peer id, different dest
|
// fixme same peer id, different dest
|
||||||
Peer p = peers.get(pid);
|
Peer p = peers.get(pid);
|
||||||
if (p == null) {
|
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
|
// don't add if spoofed
|
||||||
if (matchIP) {
|
if (matchIP) {
|
||||||
Peer p2 = peers.putIfAbsent(pid, p);
|
Peer p2 = peers.putIfAbsent(pid, p);
|
||||||
@ -218,11 +220,20 @@
|
|||||||
// snark < 0.7.13 always wants a list
|
// snark < 0.7.13 always wants a list
|
||||||
m.put("peers", java.util.Collections.EMPTY_LIST);
|
m.put("peers", java.util.Collections.EMPTY_LIST);
|
||||||
} else {
|
} else {
|
||||||
List<Peer> peerlist = new ArrayList(peers.values());
|
List<Peer> peerlist = new ArrayList<Peer>(peers.values());
|
||||||
peerlist.remove(p); // them
|
peerlist.remove(p); // them
|
||||||
if (want < size - 1) {
|
if (want < size - 1) {
|
||||||
Collections.shuffle(peerlist);
|
if (size > 150) {
|
||||||
peerlist = peerlist.subList(0, want);
|
// 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) {
|
if (compact) {
|
||||||
// old experimental way - list of hashes
|
// old experimental way - list of hashes
|
||||||
|
@ -45,7 +45,8 @@
|
|||||||
if (xff != null || xfs != null) {
|
if (xff != null || xfs != null) {
|
||||||
fail = true;
|
fail = true;
|
||||||
msg = "Non-I2P access denied";
|
msg = "Non-I2P access denied";
|
||||||
response.setStatus(403, msg);
|
//response.setStatus(403, msg);
|
||||||
|
response.setStatus(403);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean all = info_hash == null;
|
boolean all = info_hash == null;
|
||||||
@ -67,21 +68,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// build 3-level dictionary
|
// build 3-level dictionary
|
||||||
Map<String, Object> m = new HashMap(4);
|
Map<String, Object> m = new HashMap<String, Object>(4);
|
||||||
if (fail) {
|
if (fail) {
|
||||||
m.put("failure reason", msg);
|
m.put("failure reason", msg);
|
||||||
} else {
|
} else {
|
||||||
List<InfoHash> ihList = new ArrayList();
|
List<InfoHash> ihList = new ArrayList<InfoHash>();
|
||||||
if (all)
|
if (all)
|
||||||
ihList.addAll(torrents.keySet());
|
ihList.addAll(torrents.keySet());
|
||||||
else
|
else
|
||||||
ihList.add(ih);
|
ihList.add(ih);
|
||||||
Map<String, Map> files = new HashMap();
|
Map<String, Map> files = new HashMap<String, Map>();
|
||||||
for (InfoHash ihash : ihList) {
|
for (InfoHash ihash : ihList) {
|
||||||
Peers peers = torrents.get(ihash);
|
Peers peers = torrents.get(ihash);
|
||||||
if (peers == null)
|
if (peers == null)
|
||||||
continue;
|
continue;
|
||||||
Map<String, Object> dict = new HashMap();
|
Map<String, Object> dict = new HashMap<String, Object>();
|
||||||
int size = peers.size();
|
int size = peers.size();
|
||||||
int seeds = peers.countSeeds();
|
int seeds = peers.countSeeds();
|
||||||
dict.put("complete", Integer.valueOf(seeds));
|
dict.put("complete", Integer.valueOf(seeds));
|
||||||
|
@ -40,7 +40,8 @@
|
|||||||
|
|
||||||
if (xff != null || xfs != null) {
|
if (xff != null || xfs != null) {
|
||||||
String msg = "Non-I2P access denied";
|
String msg = "Non-I2P access denied";
|
||||||
response.setStatus(403, msg);
|
//response.setStatus(403, msg);
|
||||||
|
response.setStatus(403);
|
||||||
out.println(msg);
|
out.println(msg);
|
||||||
} else if (req == null) {
|
} else if (req == null) {
|
||||||
// probe
|
// probe
|
||||||
@ -63,7 +64,8 @@
|
|||||||
// all the peers
|
// all the peers
|
||||||
Torrents torrents = ZzzOTController.getTorrents();
|
Torrents torrents = ZzzOTController.getTorrents();
|
||||||
if (torrents == null) {
|
if (torrents == null) {
|
||||||
response.setStatus(503, "Down");
|
//response.setStatus(503, "Down");
|
||||||
|
response.setStatus(503);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (InfoHash ihash : torrents.keySet()) {
|
for (InfoHash ihash : torrents.keySet()) {
|
||||||
@ -92,7 +94,8 @@
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// error code
|
// error code
|
||||||
response.setStatus(406, "Bad request");
|
//response.setStatus(406, "Bad request");
|
||||||
|
response.setStatus(406);
|
||||||
out.println("SC_NOT_ACCEPTABLE");
|
out.println("SC_NOT_ACCEPTABLE");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user