propagate from branch 'i2p.i2p' (head 3d405c867f6903bf1d69b04c1daebf3146882525)

to branch 'i2p.i2p.zzz.test4' (head bfd85b10fdd1542526a4b9c53e5d4a733087f317)
This commit is contained in:
zzz
2010-12-15 15:09:48 +00:00
72 changed files with 2147 additions and 736 deletions

View File

@ -16,6 +16,7 @@ import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.concurrent.RejectedExecutionException;
import net.i2p.I2PAppContext;
import net.i2p.data.ByteArray;
@ -228,7 +229,15 @@ class HTTPResponseOutputStream extends FilterOutputStream {
//out.flush();
PipedInputStream pi = new PipedInputStream();
PipedOutputStream po = new PipedOutputStream(pi);
new I2PAppThread(new Pusher(pi, out), "HTTP decompressor").start();
// Run in the client thread pool, as there should be an unused thread
// there after the accept().
// Overridden in I2PTunnelHTTPServer, where it does not use the client pool.
try {
I2PTunnelClientBase._executor.execute(new Pusher(pi, out));
} catch (RejectedExecutionException ree) {
// shouldn't happen
throw ree;
}
out = po;
}

View File

@ -16,8 +16,6 @@ import net.i2p.util.Log;
public class I2PTunnelClient extends I2PTunnelClientBase {
private static final Log _log = new Log(I2PTunnelClient.class);
/** list of Destination objects that we point at */
protected List<Destination> dests;
private static final long DEFAULT_READ_TIMEOUT = 5*60*1000; // -1

View File

@ -17,6 +17,13 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadFactory;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
@ -34,9 +41,9 @@ import net.i2p.util.SimpleTimer;
public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runnable {
private static final Log _log = new Log(I2PTunnelClientBase.class);
protected I2PAppContext _context;
protected Logging l;
protected final Log _log;
protected final I2PAppContext _context;
protected final Logging l;
static final long DEFAULT_CONNECT_TIMEOUT = 60 * 1000;
@ -64,35 +71,24 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
private String handlerName;
private String privKeyFile;
// private Object conLock = new Object();
/** List of Socket for those accept()ed but not yet started up */
protected final List _waitingSockets = new ArrayList(4); // FIXME should be final and use a factory. FIXME
/** How many connections will we allow to be in the process of being built at once? */
private int _numConnectionBuilders;
/** How long will we allow sockets to sit in the _waitingSockets map before killing them? */
private int _maxWaitTime;
/**
* How many concurrent connections this I2PTunnel instance will allow to be
* in the process of connecting (or if less than 1, there is no limit)?
*/
public static final String PROP_NUM_CONNECTION_BUILDERS = "i2ptunnel.numConnectionBuilders";
/**
* How long will we let a socket wait after being accept()ed without getting
* pumped through a connection builder (in milliseconds). If this time is
* reached, the socket is unceremoniously closed and discarded. If the max
* wait time is less than 1, there is no limit.
*
*/
public static final String PROP_MAX_WAIT_TIME = "i2ptunnel.maxWaitTime";
private static final int DEFAULT_NUM_CONNECTION_BUILDERS = 5;
private static final int DEFAULT_MAX_WAIT_TIME = 30*1000;
// true if we are chained from a server.
private boolean chained = false;
/** how long to wait before dropping an idle thread */
private static final long HANDLER_KEEPALIVE_MS = 2*60*1000;
/**
* We keep a static pool of socket handlers for all clients,
* as there is no need for isolation on the client side.
* Extending classes may use it for other purposes.
* Not for use by servers, as there is no limit on threads.
*/
static final Executor _executor;
private static int _executorThreadCount;
static {
_executor = new CustomThreadPoolExecutor();
}
public I2PTunnelClientBase(int localPort, Logging l, I2PSocketManager sktMgr,
I2PTunnel tunnel, EventDispatcher notifyThis, long clientId )
throws IllegalArgumentException {
@ -109,9 +105,9 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
_context.statManager().createRateStat("i2ptunnel.client.closeNoBacklog", "How many pending sockets remain when it was removed prior to backlog timeout?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_context.statManager().createRateStat("i2ptunnel.client.manageTime", "How long it takes to accept a socket and fire it into an i2ptunnel runner (or queue it for the pool)?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_context.statManager().createRateStat("i2ptunnel.client.buildRunTime", "How long it takes to run a queued socket into an i2ptunnel runner?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_log = _context.logManager().getLog(getClass());
Thread t = new I2PAppThread(this);
t.setName("Client " + _clientId);
Thread t = new I2PAppThread(this, "Client " + tunnel.listenHost + ':' + localPort);
listenerReady = false;
t.start();
open = true;
@ -125,8 +121,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
configurePool(tunnel);
if (open && listenerReady) {
l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort);
notifyEvent("openBaseClientResult", "ok");
@ -135,6 +129,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
notifyEvent("openBaseClientResult", "error");
}
}
public I2PTunnelClientBase(int localPort, boolean ownDest, Logging l,
EventDispatcher notifyThis, String handlerName,
I2PTunnel tunnel) throws IllegalArgumentException {
@ -163,6 +158,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
_context.statManager().createRateStat("i2ptunnel.client.closeNoBacklog", "How many pending sockets remain when it was removed prior to backlog timeout?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_context.statManager().createRateStat("i2ptunnel.client.manageTime", "How long it takes to accept a socket and fire it into an i2ptunnel runner (or queue it for the pool)?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_context.statManager().createRateStat("i2ptunnel.client.buildRunTime", "How long it takes to run a queued socket into an i2ptunnel runner?", "I2PTunnel", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_log = _context.logManager().getLog(getClass());
// normalize path so we can find it
if (pkf != null) {
@ -210,8 +206,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
configurePool(tunnel);
if (open && listenerReady) {
if (openNow)
l.log("Client ready, listening on " + tunnel.listenHost + ':' + localPort);
@ -224,37 +218,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
/**
* build and configure the pool handling accept()ed but not yet
* established connections
*
*/
private void configurePool(I2PTunnel tunnel) {
//_waitingSockets = new ArrayList(4);
Properties opts = tunnel.getClientOptions();
String maxWait = opts.getProperty(PROP_MAX_WAIT_TIME, DEFAULT_MAX_WAIT_TIME+"");
try {
_maxWaitTime = Integer.parseInt(maxWait);
} catch (NumberFormatException nfe) {
_maxWaitTime = DEFAULT_MAX_WAIT_TIME;
}
String numBuild = opts.getProperty(PROP_NUM_CONNECTION_BUILDERS, DEFAULT_NUM_CONNECTION_BUILDERS+"");
try {
_numConnectionBuilders = Integer.parseInt(numBuild);
} catch (NumberFormatException nfe) {
_numConnectionBuilders = DEFAULT_NUM_CONNECTION_BUILDERS;
}
for (int i = 0; i < _numConnectionBuilders; i++) {
String name = "ClientBuilder" + _clientId + '.' + i;
I2PAppThread b = new I2PAppThread(new TunnelConnectionBuilder(), name);
b.setDaemon(true);
b.start();
}
}
/**
* Sets the this.sockMgr field if it is null, or if we want a new one
*
@ -321,6 +284,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
* badly that we cant create a socketManager
*/
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel, String pkf) {
// shadows instance _log
Log _log = tunnel.getContext().logManager().getLog(I2PTunnelClientBase.class);
if (socketManager != null) {
I2PSession s = socketManager.getSession();
if ( (s == null) || (s.isClosed()) ) {
@ -378,6 +343,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
* badly that we cant create a socketManager
*/
protected static I2PSocketManager buildSocketManager(I2PTunnel tunnel, String pkf, Logging log) {
// shadows instance _log
Log _log = tunnel.getContext().logManager().getLog(I2PTunnelClientBase.class);
Properties props = new Properties();
props.putAll(tunnel.getClientOptions());
int portNum = 7654;
@ -537,7 +504,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
synchronized (this) {
notifyAll();
}
synchronized (_waitingSockets) { _waitingSockets.notifyAll(); }
return;
}
ss = new ServerSocket(localPort, 0, addr);
@ -566,12 +532,9 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
while (true) {
while (open) {
Socket s = ss.accept();
long before = System.currentTimeMillis();
manageConnection(s);
long total = System.currentTimeMillis() - before;
_context.statManager().addRateData("i2ptunnel.client.manageTime", total, total);
}
} catch (IOException ex) {
if (open) {
@ -586,9 +549,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
notifyAll();
}
}
synchronized (_waitingSockets) {
_waitingSockets.notifyAll();
}
}
/**
@ -598,24 +558,38 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
*/
protected void manageConnection(Socket s) {
if (s == null) return;
if (_numConnectionBuilders <= 0) {
new I2PAppThread(new BlockingRunner(s), "Clinet run").start();
return;
try {
_executor.execute(new BlockingRunner(s));
} catch (RejectedExecutionException ree) {
// should never happen, we have an unbounded pool and never stop the executor
try {
s.close();
} catch (IOException ioe) {}
}
if (_maxWaitTime > 0)
SimpleScheduler.getInstance().addEvent(new CloseEvent(s), _maxWaitTime);
}
synchronized (_waitingSockets) {
_waitingSockets.add(s);
_waitingSockets.notifyAll();
/**
* Not really needed for now but in case we want to add some hooks like afterExecute().
*/
private static class CustomThreadPoolExecutor extends ThreadPoolExecutor {
public CustomThreadPoolExecutor() {
super(0, Integer.MAX_VALUE, HANDLER_KEEPALIVE_MS, TimeUnit.MILLISECONDS,
new SynchronousQueue(), new CustomThreadFactory());
}
}
/** just to set the name and set Daemon */
private static class CustomThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
Thread rv = Executors.defaultThreadFactory().newThread(r);
rv.setName("I2PTunnel Client Runner " + (++_executorThreadCount));
rv.setDaemon(true);
return rv;
}
}
/**
* Blocking runner, used during the connection establishment whenever we
* are not using the queued builders.
*
* Blocking runner, used during the connection establishment
*/
private class BlockingRunner implements Runnable {
private Socket _s;
@ -625,32 +599,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
/**
* Remove and close the socket from the waiting list, if it is still there.
*
*/
private class CloseEvent implements SimpleTimer.TimedEvent {
private Socket _s;
public CloseEvent(Socket s) { _s = s; }
public void timeReached() {
int remaining = 0;
boolean stillWaiting = false;
synchronized (_waitingSockets) {
stillWaiting = _waitingSockets.remove(_s);
remaining = _waitingSockets.size();
}
if (stillWaiting) {
try { _s.close(); } catch (IOException ioe) {}
if (_log.shouldLog(Log.INFO)) {
_context.statManager().addRateData("i2ptunnel.client.closeBacklog", remaining, 0);
_log.info("Closed a waiting socket because of backlog");
}
} else {
_context.statManager().addRateData("i2ptunnel.client.closeNoBacklog", remaining, 0);
}
}
}
public boolean close(boolean forced) {
if (_log.shouldLog(Log.INFO))
_log.info("close() called: forced = " + forced + " open = " + open + " sockMgr = " + sockMgr);
@ -688,7 +636,6 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
//l.log("Client closed.");
}
synchronized (_waitingSockets) { _waitingSockets.notifyAll(); }
return true;
}
@ -696,40 +643,10 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
try {
s.close();
} catch (IOException ex) {
_log.error("Could not close socket", ex);
//_log.error("Could not close socket", ex);
}
}
/**
* Pool runner pulling sockets off the waiting list and pushing them
* through clientConnectionRun. This dies when the I2PTunnel instance
* is closed.
*
*/
private class TunnelConnectionBuilder implements Runnable {
public void run() {
Socket s = null;
while (open) {
try {
synchronized (_waitingSockets) {
if (_waitingSockets.isEmpty())
_waitingSockets.wait();
else
s = (Socket)_waitingSockets.remove(0);
}
} catch (InterruptedException ie) {}
if (s != null) {
long before = System.currentTimeMillis();
clientConnectionRun(s);
long total = System.currentTimeMillis() - before;
_context.statManager().addRateData("i2ptunnel.client.buildRunTime", total, 0);
}
s = null;
}
}
}
/**
* Manage a connection in a separate thread. This only works if
* you do not override manageConnection()

View File

@ -58,7 +58,6 @@ import net.i2p.util.Log;
* @author zzz a stripped-down I2PTunnelHTTPClient
*/
public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements Runnable {
private static final Log _log = new Log(I2PTunnelConnectClient.class);
private final static byte[] ERR_DESTINATION_UNKNOWN =
("HTTP/1.1 503 Service Unavailable\r\n"+
@ -340,8 +339,8 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
_requestId = id;
}
public void run() {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Timeout occured requesting " + _target);
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Timeout occured requesting " + _target);
handleConnectClientException(new RuntimeException("Timeout"), _out,
_target, _usingProxy, _wwwProxy, _requestId);
closeSocket(_socket);

View File

@ -11,7 +11,6 @@ import net.i2p.util.EventDispatcher;
import net.i2p.util.Log;
public class I2PTunnelHTTPBidirServer extends I2PTunnelHTTPServer {
private final static Log log = new Log(I2PTunnelHTTPBidirServer.class);
public I2PTunnelHTTPBidirServer(InetAddress host, int port, int proxyport, String privData, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privData, spoofHost, l, notifyThis, tunnel);

View File

@ -61,7 +61,6 @@ import net.i2p.util.Translate;
*
*/
public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runnable {
private static final Log _log = new Log(I2PTunnelHTTPClient.class);
private HashMap addressHelpers = new HashMap();
@ -894,15 +893,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
_requestId = id;
}
public void run() {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Timeout occured requesting " + _target);
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Timeout occured requesting " + _target);
handleHTTPClientException(new RuntimeException("Timeout"), _out,
_target, _usingProxy, _wwwProxy, _requestId);
closeSocket(_socket);
}
}
private static String DEFAULT_JUMP_SERVERS =
public static final String DEFAULT_JUMP_SERVERS =
"http://i2host.i2p/cgi-bin/i2hostjump?," +
"http://stats.i2p/cgi-bin/jump.cgi?a=," +
"http://i2jump.i2p/";
@ -940,8 +939,12 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
// Skip jump servers we don't know
String jumphost = jurl.substring(7); // "http://"
jumphost = jumphost.substring(0, jumphost.indexOf('/'));
Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(jumphost);
if (dest == null) continue;
if (!jumphost.endsWith(".i2p"))
continue;
if (!jumphost.endsWith(".b32.i2p")) {
Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(jumphost);
if (dest == null) continue;
}
out.write("<br><a href=\"".getBytes());
out.write(jurl.getBytes());

View File

@ -25,7 +25,7 @@ import net.i2p.util.Log;
* @since 0.8.2
*/
public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implements Runnable {
private static final Log _log = new Log(I2PTunnelHTTPClientBase.class);
protected final List<String> _proxyList;
protected final static byte[] ERR_NO_OUTPROXY =

View File

@ -31,7 +31,7 @@ import net.i2p.data.Base32;
*
*/
public class I2PTunnelHTTPServer extends I2PTunnelServer {
private final static Log _log = new Log(I2PTunnelHTTPServer.class);
/** what Host: should we seem to be to the webserver? */
private String _spoofHost;
private static final String HASH_HEADER = "X-I2P-DestHash";
@ -40,6 +40,20 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
private static final String[] CLIENT_SKIPHEADERS = {HASH_HEADER, DEST64_HEADER, DEST32_HEADER};
private static final String SERVER_HEADER = "Server";
private static final String[] SERVER_SKIPHEADERS = {SERVER_HEADER};
private static final long HEADER_TIMEOUT = 60*1000;
private final static byte[] ERR_UNAVAILABLE =
("HTTP/1.1 503 Service Unavailable\r\n"+
"Content-Type: text/html; charset=iso-8859-1\r\n"+
"Cache-control: no-cache\r\n"+
"Connection: close\r\n"+
"Proxy-Connection: close\r\n"+
"\r\n"+
"<html><head><title>503 Service Unavailable<title></head>\n"+
"<body><h2>503 Service Unavailable</h2>\n" +
"<p>This I2P eepsite is unavailable. It may be down or undergoing maintenance.</p>\n" +
"</body></html>")
.getBytes();
public I2PTunnelHTTPServer(InetAddress host, int port, String privData, String spoofHost, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(host, port, privData, l, notifyThis, tunnel);
@ -73,8 +87,9 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
//local is fast, so synchronously. Does not need that many
//threads.
try {
// give them 5 seconds to send in the HTTP request
socket.setReadTimeout(5*1000);
// The headers _should_ be in the first packet, but
// may not be, depending on the client-side options
socket.setReadTimeout(HEADER_TIMEOUT);
InputStream in = socket.getInputStream();
@ -130,13 +145,24 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
} else {
new I2PTunnelRunner(s, socket, slock, null, modifiedHeader.getBytes(), null);
}
long afterHandle = getTunnel().getContext().clock().now();
long timeToHandle = afterHandle - afterAccept;
getTunnel().getContext().statManager().addRateData("i2ptunnel.httpserver.blockingHandleTime", timeToHandle, 0);
if ( (timeToHandle > 1000) && (_log.shouldLog(Log.WARN)) )
_log.warn("Took a while to handle the request for " + remoteHost + ':' + remotePort +
" [" + timeToHandle + ", socket create: " + (afterSocket-afterAccept) + "]");
} catch (SocketException ex) {
try {
// Send a 503, so the user doesn't get an HTTP Proxy error message
// and blame his router or the network.
socket.getOutputStream().write(ERR_UNAVAILABLE);
} catch (IOException ioe) {}
try {
socket.close();
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error while closing the received i2p con", ex);
}
} catch (IOException ioe) {}
if (_log.shouldLog(Log.ERROR))
_log.error("Error connecting to HTTP server " + remoteHost + ':' + remotePort, ex);
} catch (IOException ex) {
try {
socket.close();
@ -150,12 +176,6 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
if (_log.shouldLog(Log.ERROR))
_log.error("OOM in HTTP server", oom);
}
long afterHandle = getTunnel().getContext().clock().now();
long timeToHandle = afterHandle - afterAccept;
getTunnel().getContext().statManager().addRateData("i2ptunnel.httpserver.blockingHandleTime", timeToHandle, 0);
if ( (timeToHandle > 1000) && (_log.shouldLog(Log.WARN)) )
_log.warn("Took a while to handle the request [" + timeToHandle + ", socket create: " + (afterSocket-afterAccept) + "]");
}
private static class CompressedRequestor implements Runnable {
@ -169,6 +189,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
_headers = headers;
_ctx = ctx;
}
public void run() {
if (_log.shouldLog(Log.INFO))
_log.info("Compressed requestor running");
@ -183,7 +204,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
_log.info("request headers: " + _headers);
serverout.write(_headers.getBytes());
browserin = _browser.getInputStream();
I2PAppThread sender = new I2PAppThread(new Sender(serverout, browserin, "server: browser to server"), Thread.currentThread().getName() + "hcs");
I2PAppThread sender = new I2PAppThread(new Sender(serverout, browserin, "server: browser to server", _log), Thread.currentThread().getName() + "hcs");
sender.start();
browserout = _browser.getOutputStream();
@ -233,14 +254,19 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
}
private static class Sender implements Runnable {
private OutputStream _out;
private InputStream _in;
private String _name;
public Sender(OutputStream out, InputStream in, String name) {
private final OutputStream _out;
private final InputStream _in;
private final String _name;
// shadows _log in super()
private final Log _log;
public Sender(OutputStream out, InputStream in, String name, Log log) {
_out = out;
_in = in;
_name = name;
_log = log;
}
public void run() {
if (_log.shouldLog(Log.INFO))
_log.info(_name + ": Begin sending");
@ -277,16 +303,16 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
protected boolean shouldCompress() { return true; }
@Override
protected void finishHeaders() throws IOException {
if (_log.shouldLog(Log.INFO))
_log.info("Including x-i2p-gzip as the content encoding in the response");
//if (_log.shouldLog(Log.INFO))
// _log.info("Including x-i2p-gzip as the content encoding in the response");
out.write("Content-encoding: x-i2p-gzip\r\n".getBytes());
super.finishHeaders();
}
@Override
protected void beginProcessing() throws IOException {
if (_log.shouldLog(Log.INFO))
_log.info("Beginning compression processing");
//if (_log.shouldLog(Log.INFO))
// _log.info("Beginning compression processing");
//out.flush();
_gzipOut = new InternalGZIPOutputStream(out);
out = _gzipOut;

View File

@ -20,8 +20,6 @@ import net.i2p.util.Log;
*/
public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable {
private static final Log _log = new Log(I2PTunnelIRCClient.class);
/** used to assign unique IDs to the threads / clients. no logic or functionality */
private static volatile long __clientId = 0;
@ -130,6 +128,8 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
private Socket local;
private I2PSocket remote;
private StringBuffer expectedPong;
// shadows _log in super()
private final Log _log = new Log(I2PTunnelIRCClient.class);
public IrcInboundFilter(Socket _local, I2PSocket _remote, StringBuffer pong) {
local=_local;
@ -207,6 +207,8 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
private Socket local;
private I2PSocket remote;
private StringBuffer expectedPong;
// shadows _log in super()
private final Log _log = new Log(I2PTunnelIRCClient.class);
public IrcOutboundFilter(Socket _local, I2PSocket _remote, StringBuffer pong) {
local=_local;
@ -308,7 +310,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
try { command = field[idx++]; }
catch (IndexOutOfBoundsException ioobe) // wtf, server sent borked command?
{
_log.warn("Dropping defective message: index out of bounds while extracting command.");
//_log.warn("Dropping defective message: index out of bounds while extracting command.");
return null;
}
@ -431,13 +433,13 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
rv = "PING " + field[1];
expectedPong.append("PONG ").append(field[2]).append(" :").append(field[1]); // PONG serverLocation nonce
} else {
if (_log.shouldLog(Log.ERROR))
_log.error("IRC client sent a PING we don't understand, filtering it (\"" + s + "\")");
//if (_log.shouldLog(Log.ERROR))
// _log.error("IRC client sent a PING we don't understand, filtering it (\"" + s + "\")");
rv = null;
}
if (_log.shouldLog(Log.WARN))
_log.warn("sending ping [" + rv + "], waiting for [" + expectedPong + "] orig was [" + s + "]");
//if (_log.shouldLog(Log.WARN))
// _log.warn("sending ping [" + rv + "], waiting for [" + expectedPong + "] orig was [" + s + "]");
return rv;
}

View File

@ -61,9 +61,7 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
public static final String PROP_WEBIRC_SPOOF_IP_DEFAULT="127.0.0.1";
public static final String PROP_HOSTNAME="ircserver.fakeHostname";
public static final String PROP_HOSTNAME_DEFAULT="%f.b32.i2p";
private static final Log _log = new Log(I2PTunnelIRCServer.class);
private static final long HEADER_TIMEOUT = 60*1000;
/**
* @throws IllegalArgumentException if the I2PTunnel does not contain
@ -108,8 +106,9 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
try {
String modifiedRegistration;
if(!this.method.equals("webirc")) {
// give them 15 seconds to send in the request
socket.setReadTimeout(15*1000);
// The headers _should_ be in the first packet, but
// may not be, depending on the client-side options
socket.setReadTimeout(HEADER_TIMEOUT);
InputStream in = socket.getInputStream();
modifiedRegistration = filterRegistration(in, cloakDest(socket.getPeerDestination()));
socket.setReadTimeout(readTimeout);
@ -126,12 +125,12 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
Socket s = new Socket(remoteHost, remotePort);
new I2PTunnelRunner(s, socket, slock, null, modifiedRegistration.getBytes(), null);
} catch (SocketException ex) {
// TODO send the equivalent of a 503?
try {
socket.close();
} catch (IOException ioe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error while closing the received i2p con", ex);
}
} catch (IOException ioe) {}
if (_log.shouldLog(Log.ERROR))
_log.error("Error connecting to IRC server " + remoteHost + ':' + remotePort, ex);
} catch (IOException ex) {
try {
socket.close();
@ -181,8 +180,8 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
if (++lineCount > 10)
throw new IOException("Too many lines before USER or SERVER, giving up");
s = s.trim();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Got line: " + s);
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("Got line: " + s);
String field[]=s.split(" ",5);
String command;
@ -214,8 +213,8 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
if ("SERVER".equalsIgnoreCase(command))
break;
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("All done, sending: " + buf.toString());
//if (_log.shouldLog(Log.DEBUG))
// _log.debug("All done, sending: " + buf.toString());
return buf.toString();
}

View File

@ -16,6 +16,12 @@ import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.Iterator;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadFactory;
import net.i2p.I2PAppContext;
import net.i2p.I2PException;
@ -30,8 +36,7 @@ import net.i2p.util.Log;
public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
private final static Log _log = new Log(I2PTunnelServer.class);
protected final Log _log;
protected I2PSocketManager sockMgr;
protected I2PServerSocket i2pss;
@ -48,12 +53,17 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
/** default timeout to 3 minutes - override if desired */
protected long readTimeout = DEFAULT_READ_TIMEOUT;
private static final boolean DEFAULT_USE_POOL = false;
/** do we use threads? default true (ignored for standard servers, always false) */
private static final String PROP_USE_POOL = "i2ptunnel.usePool";
private static final boolean DEFAULT_USE_POOL = true;
protected static volatile long __serverId = 0;
/** max number of threads - this many slowlorisses will DOS this server, but too high could OOM the JVM */
private static final String PROP_HANDLER_COUNT = "i2ptunnel.blockingHandlerCount";
private static final int DEFAULT_HANDLER_COUNT = 10;
private static final int DEFAULT_HANDLER_COUNT = 65;
/** min number of threads */
private static final int MIN_HANDLERS = 0;
/** how long to wait before dropping an idle thread */
private static final long HANDLER_KEEPALIVE_MS = 30*1000;
protected I2PTunnelTask task = null;
protected boolean bidir = false;
@ -67,8 +77,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
*/
public I2PTunnelServer(InetAddress host, int port, String privData, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super("Server at " + host + ':' + port, notifyThis, tunnel);
_log = tunnel.getContext().logManager().getLog(getClass());
ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(privData));
SetUsePool(tunnel);
init(host, port, bais, privData, l);
}
@ -79,7 +89,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
public I2PTunnelServer(InetAddress host, int port, File privkey, String privkeyname, Logging l,
EventDispatcher notifyThis, I2PTunnel tunnel) {
super("Server at " + host + ':' + port, notifyThis, tunnel);
SetUsePool(tunnel);
_log = tunnel.getContext().logManager().getLog(getClass());
FileInputStream fis = null;
try {
fis = new FileInputStream(privkey);
@ -99,19 +109,10 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
*/
public I2PTunnelServer(InetAddress host, int port, InputStream privData, String privkeyname, Logging l, EventDispatcher notifyThis, I2PTunnel tunnel) {
super("Server at " + host + ':' + port, notifyThis, tunnel);
SetUsePool(tunnel);
_log = tunnel.getContext().logManager().getLog(getClass());
init(host, port, privData, privkeyname, l);
}
private void SetUsePool(I2PTunnel Tunnel) {
String usePool = Tunnel.getClientOptions().getProperty("i2ptunnel.usePool");
if (usePool != null)
_usePool = "true".equalsIgnoreCase(usePool);
else
_usePool = DEFAULT_USE_POOL;
}
private static final int RETRY_DELAY = 20*1000;
private static final int MAX_RETRIES = 4;
@ -143,6 +144,16 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
return;
}
// extending classes default to threaded, but for a standard server, we can't get slowlorissed
_usePool = !getClass().equals(I2PTunnelServer.class);
if (_usePool) {
String usePool = getTunnel().getClientOptions().getProperty(PROP_USE_POOL);
if (usePool != null)
_usePool = "true".equalsIgnoreCase(usePool);
else
_usePool = DEFAULT_USE_POOL;
}
// Todo: Can't stop a tunnel from the UI while it's in this loop (no session yet)
int retries = 0;
while (sockMgr == null) {
@ -199,8 +210,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
*
*/
public void startRunning() {
Thread t = new I2PAppThread(this);
t.setName("Server " + (++__serverId));
Thread t = new I2PAppThread(this, "Server " + remoteHost + ':' + remotePort, true);
t.start();
}
@ -236,7 +246,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
}
return false;
}
l.log("Stopping tunnels for server at " + getTunnel().listenHost + ':' + this.remotePort);
l.log("Stopping tunnels for server at " + this.remoteHost + ':' + this.remotePort);
try {
if (i2pss != null) i2pss.close();
getTunnel().removeSession(sockMgr.getSession());
@ -259,67 +269,106 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
rv = Integer.parseInt(cnt);
if (rv <= 0)
rv = DEFAULT_HANDLER_COUNT;
} catch (NumberFormatException nfe) {
rv = DEFAULT_HANDLER_COUNT;
}
} catch (NumberFormatException nfe) {}
}
return rv;
}
/**
* If usePool is set, this starts the executor pool.
* Then, do the accept() loop, and either
* hands each I2P socket to the executor or runs it in-line.
*/
public void run() {
if (shouldUsePool()) {
I2PServerSocket i2pS_S = sockMgr.getServerSocket();
int handlers = getHandlerCount();
for (int i = 0; i < handlers; i++) {
I2PAppThread handler = new I2PAppThread(new Handler(i2pS_S), "Handle Server " + i);
handler.start();
}
} else {
I2PServerSocket i2pS_S = sockMgr.getServerSocket();
while (true) {
try {
final I2PSocket i2ps = i2pS_S.accept();
if (i2ps == null) throw new I2PException("I2PServerSocket closed");
new I2PAppThread(new Runnable() { public void run() { blockingHandle(i2ps); } }).start();
} catch (I2PException ipe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error accepting - KILLING THE TUNNEL SERVER", ipe);
return;
} catch (ConnectException ce) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error accepting", ce);
// not killing the server..
} catch(SocketTimeoutException ste) {
// ignored, we never set the timeout
I2PServerSocket i2pS_S = sockMgr.getServerSocket();
ThreadPoolExecutor executor = null;
if (_log.shouldLog(Log.WARN)) {
if (_usePool)
_log.warn("Starting executor with " + getHandlerCount() + " threads max");
else
_log.warn("Threads disabled, running blockingHandles inline");
}
if (_usePool) {
executor = new CustomThreadPoolExecutor(getHandlerCount(), "ServerHandler pool " + remoteHost + ':' + remotePort);
}
while (open) {
try {
final I2PSocket i2ps = i2pS_S.accept();
if (i2ps == null) throw new I2PException("I2PServerSocket closed");
if (_usePool) {
try {
executor.execute(new Handler(i2ps));
} catch (RejectedExecutionException ree) {
try {
i2ps.close();
} catch (IOException ioe) {}
if (open && _log.shouldLog(Log.ERROR))
_log.error("ServerHandler queue full for " + remoteHost + ':' + remotePort +
"; increase " + PROP_HANDLER_COUNT + '?', ree);
}
} else {
// use only for standard servers that can't get slowlorissed! Not for http or irc
blockingHandle(i2ps);
}
} catch (I2PException ipe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error accepting - KILLING THE TUNNEL SERVER", ipe);
return;
} catch (ConnectException ce) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error accepting", ce);
// not killing the server..
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException ie) {}
} catch(SocketTimeoutException ste) {
// ignored, we never set the timeout
}
}
if (executor != null)
executor.shutdownNow();
}
/**
* Not really needed for now but in case we want to add some hooks like afterExecute().
*/
private static class CustomThreadPoolExecutor extends ThreadPoolExecutor {
public CustomThreadPoolExecutor(int max, String name) {
super(MIN_HANDLERS, max, HANDLER_KEEPALIVE_MS, TimeUnit.MILLISECONDS,
new SynchronousQueue(), new CustomThreadFactory(name));
}
}
/** just to set the name and set Daemon */
private static class CustomThreadFactory implements ThreadFactory {
private String _name;
public CustomThreadFactory(String name) {
_name = name;
}
public Thread newThread(Runnable r) {
Thread rv = Executors.defaultThreadFactory().newThread(r);
rv.setName(_name);
rv.setDaemon(true);
return rv;
}
}
public boolean shouldUsePool() { return _usePool; }
/**
* minor thread pool to pull off the accept() concurrently. there are still lots
* (and lots) of wasted threads within the I2PTunnelRunner, but its a start
*
* Run the blockingHandler.
*/
private class Handler implements Runnable {
private I2PServerSocket _serverSocket;
public Handler(I2PServerSocket serverSocket) {
_serverSocket = serverSocket;
private I2PSocket _i2ps;
public Handler(I2PSocket socket) {
_i2ps = socket;
}
public void run() {
while (open) {
try {
blockingHandle(_serverSocket.accept());
} catch (I2PException ex) {
_log.error("Error while waiting for I2PConnections", ex);
return;
} catch (IOException ex) {
_log.error("Error while waiting for I2PConnections", ex);
return;
}
}
blockingHandle(_i2ps);
}
}
@ -335,20 +384,21 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
Socket s = new Socket(remoteHost, remotePort);
afterSocket = I2PAppContext.getGlobalContext().clock().now();
new I2PTunnelRunner(s, socket, slock, null, null);
long afterHandle = I2PAppContext.getGlobalContext().clock().now();
long timeToHandle = afterHandle - afterAccept;
if ( (timeToHandle > 1000) && (_log.shouldLog(Log.WARN)) )
_log.warn("Took a while to handle the request for " + remoteHost + ':' + remotePort +
" [" + timeToHandle + ", socket create: " + (afterSocket-afterAccept) + "]");
} catch (SocketException ex) {
try {
socket.close();
} catch (IOException ioe) {
_log.error("Error while closing the received i2p con", ex);
}
} catch (IOException ioe) {}
if (_log.shouldLog(Log.ERROR))
_log.error("Error connecting to server " + remoteHost + ':' + remotePort, ex);
} catch (IOException ex) {
_log.error("Error while waiting for I2PConnections", ex);
}
long afterHandle = I2PAppContext.getGlobalContext().clock().now();
long timeToHandle = afterHandle - afterAccept;
if (timeToHandle > 1000)
_log.warn("Took a while to handle the request [" + timeToHandle + ", socket create: " + (afterSocket-afterAccept) + "]");
}
}

View File

@ -30,7 +30,6 @@ import net.i2p.util.Log;
*/
public class I2PSOCKSIRCTunnel extends I2PSOCKSTunnel {
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(I2PSOCKSIRCTunnel.class);
private static int __clientId = 0;
/** @param pkf private key file name or null for transient key */

View File

@ -26,7 +26,6 @@ import net.i2p.util.Log;
public class I2PSOCKSTunnel extends I2PTunnelClientBase {
private static final Log _log = new Log(I2PSOCKSTunnel.class);
private HashMap<String, List<String>> proxies = null; // port# + "" or "default" -> hostname list
protected Destination outProxyDest = null;

View File

@ -45,7 +45,6 @@ import net.i2p.util.Log;
*/
public abstract class I2PTunnelUDPClientBase extends I2PTunnelTask implements Source, Sink {
private static final Log _log = new Log(I2PTunnelUDPClientBase.class);
protected I2PAppContext _context;
protected Logging l;

View File

@ -46,7 +46,7 @@ import net.i2p.util.Log;
public class I2PTunnelUDPServerBase extends I2PTunnelTask implements Source, Sink {
private final static Log _log = new Log(I2PTunnelUDPServerBase.class);
private final Log _log;
private final Object lock = new Object();
protected Object slock = new Object();
@ -73,6 +73,7 @@ public class I2PTunnelUDPServerBase extends I2PTunnelTask implements Source, Sin
public I2PTunnelUDPServerBase(boolean verify, File privkey, String privkeyname, Logging l,
EventDispatcher notifyThis, I2PTunnel tunnel) {
super("UDPServer <- " + privkeyname, notifyThis, tunnel);
_log = tunnel.getContext().logManager().getLog(I2PTunnelUDPServerBase.class);
FileInputStream fis = null;
try {
fis = new FileInputStream(privkey);

View File

@ -18,6 +18,7 @@ import net.i2p.data.Destination;
import net.i2p.data.PrivateKeyFile;
import net.i2p.data.Signature;
import net.i2p.data.SigningPrivateKey;
import net.i2p.i2ptunnel.I2PTunnelHTTPClient;
import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
import net.i2p.i2ptunnel.TunnelController;
import net.i2p.i2ptunnel.TunnelControllerGroup;
@ -171,14 +172,23 @@ public class EditBean extends IndexBean {
return getProperty(tunnel, "i2cp.leaseSetKey", "");
}
public boolean getAccess(int tunnel) {
return getBooleanProperty(tunnel, "i2cp.enableAccessList");
public String getAccessMode(int tunnel) {
if (getBooleanProperty(tunnel, PROP_ENABLE_ACCESS_LIST))
return "1";
if (getBooleanProperty(tunnel, PROP_ENABLE_BLACKLIST))
return "2";
return "0";
}
public String getAccessList(int tunnel) {
return getProperty(tunnel, "i2cp.accessList", "").replace(",", "\n");
}
public String getJumpList(int tunnel) {
return getProperty(tunnel, I2PTunnelHTTPClient.PROP_JUMP_SERVERS,
I2PTunnelHTTPClient.DEFAULT_JUMP_SERVERS).replace(",", "\n");
}
public boolean getClose(int tunnel) {
return getBooleanProperty(tunnel, "i2cp.closeOnIdle");
}
@ -234,6 +244,35 @@ public class EditBean extends IndexBean {
return getProperty(tunnel, I2PTunnelHTTPClientBase.PROP_OUTPROXY_PW, "");
}
/** all of these are @since 0.8.3 */
public String getLimitMinute(int tunnel) {
return getProperty(tunnel, PROP_MAX_CONNS_MIN, "0");
}
public String getLimitHour(int tunnel) {
return getProperty(tunnel, PROP_MAX_CONNS_HOUR, "0");
}
public String getLimitDay(int tunnel) {
return getProperty(tunnel, PROP_MAX_CONNS_DAY, "0");
}
public String getTotalMinute(int tunnel) {
return getProperty(tunnel, PROP_MAX_TOTAL_CONNS_MIN, "0");
}
public String getTotalHour(int tunnel) {
return getProperty(tunnel, PROP_MAX_TOTAL_CONNS_HOUR, "0");
}
public String getTotalDay(int tunnel) {
return getProperty(tunnel, PROP_MAX_TOTAL_CONNS_DAY, "0");
}
public String getMaxStreams(int tunnel) {
return getProperty(tunnel, PROP_MAX_STREAMS, "0");
}
private int getProperty(int tunnel, String prop, int def) {
TunnelController tun = getController(tunnel);
if (tun != null) {
@ -270,7 +309,14 @@ public class EditBean extends IndexBean {
return false;
}
/** @since 0.8.3 */
public boolean isRouterContext() {
return _context.isRouterContext();
}
public String getI2CPHost(int tunnel) {
if (_context.isRouterContext())
return _("internal");
TunnelController tun = getController(tunnel);
if (tun != null)
return tun.getI2CPHost();
@ -279,6 +325,8 @@ public class EditBean extends IndexBean {
}
public String getI2CPPort(int tunnel) {
if (_context.isRouterContext())
return _("internal");
TunnelController tun = getController(tunnel);
if (tun != null)
return tun.getI2CPPort();

View File

@ -24,6 +24,7 @@ import net.i2p.data.Certificate;
import net.i2p.data.Destination;
import net.i2p.data.PrivateKeyFile;
import net.i2p.data.SessionKey;
import net.i2p.i2ptunnel.I2PTunnelHTTPClient;
import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
import net.i2p.i2ptunnel.TunnelController;
import net.i2p.i2ptunnel.TunnelControllerGroup;
@ -537,11 +538,11 @@ public class IndexBean {
public void setDescription(String description) {
_description = (description != null ? description.trim() : null);
}
/** I2CP host the router is on */
/** I2CP host the router is on, ignored when in router context */
public void setClientHost(String host) {
_i2cpHost = (host != null ? host.trim() : null);
}
/** I2CP port the router is on */
/** I2CP port the router is on, ignored when in router context */
public void setClientport(String port) {
_i2cpPort = (port != null ? port.trim() : null);
}
@ -643,9 +644,17 @@ public class IndexBean {
public void setEncrypt(String moo) {
_booleanOptions.add("i2cp.encryptLeaseSet");
}
public void setAccess(String moo) {
_booleanOptions.add("i2cp.enableAccessList");
protected static final String PROP_ENABLE_ACCESS_LIST = "i2cp.enableAccessList";
protected static final String PROP_ENABLE_BLACKLIST = "i2cp.enableBlackList";
public void setAccessMode(String val) {
if ("1".equals(val))
_booleanOptions.add(PROP_ENABLE_ACCESS_LIST);
else if ("2".equals(val))
_booleanOptions.add(PROP_ENABLE_BLACKLIST);
}
public void setDelayOpen(String moo) {
_booleanOptions.add("i2cp.delayOpen");
}
@ -671,10 +680,17 @@ public class IndexBean {
if (val != null)
_otherOptions.put("i2cp.leaseSetKey", val.trim());
}
public void setAccessList(String val) {
if (val != null)
_otherOptions.put("i2cp.accessList", val.trim().replace("\r\n", ",").replace("\n", ",").replace(" ", ","));
}
public void setJumpList(String val) {
if (val != null)
_otherOptions.put(I2PTunnelHTTPClient.PROP_JUMP_SERVERS, val.trim().replace("\r\n", ",").replace("\n", ",").replace(" ", ","));
}
public void setCloseTime(String val) {
if (val != null) {
try {
@ -712,6 +728,50 @@ public class IndexBean {
_otherOptions.put(I2PTunnelHTTPClientBase.PROP_OUTPROXY_PW, s.trim());
}
/** all of these are @since 0.8.3 */
protected static final String PROP_MAX_CONNS_MIN = "i2p.streaming.maxConnsPerMinute";
protected static final String PROP_MAX_CONNS_HOUR = "i2p.streaming.maxConnsPerHour";
protected static final String PROP_MAX_CONNS_DAY = "i2p.streaming.maxConnsPerDay";
protected static final String PROP_MAX_TOTAL_CONNS_MIN = "i2p.streaming.maxTotalConnsPerMinute";
protected static final String PROP_MAX_TOTAL_CONNS_HOUR = "i2p.streaming.maxTotalConnsPerHour";
protected static final String PROP_MAX_TOTAL_CONNS_DAY = "i2p.streaming.maxTotalConnsPerDay";
protected static final String PROP_MAX_STREAMS = "i2p.streaming.maxConcurrentStreams";
public void setLimitMinute(String s) {
if (s != null)
_otherOptions.put(PROP_MAX_CONNS_MIN, s.trim());
}
public void setLimitHour(String s) {
if (s != null)
_otherOptions.put(PROP_MAX_CONNS_HOUR, s.trim());
}
public void setLimitDay(String s) {
if (s != null)
_otherOptions.put(PROP_MAX_CONNS_DAY, s.trim());
}
public void setTotalMinute(String s) {
if (s != null)
_otherOptions.put(PROP_MAX_TOTAL_CONNS_MIN, s.trim());
}
public void setTotalHour(String s) {
if (s != null)
_otherOptions.put(PROP_MAX_TOTAL_CONNS_HOUR, s.trim());
}
public void setTotalDay(String s) {
if (s != null)
_otherOptions.put(PROP_MAX_TOTAL_CONNS_DAY, s.trim());
}
public void setMaxStreams(String s) {
if (s != null)
_otherOptions.put(PROP_MAX_STREAMS, s.trim());
}
/** params needed for hashcash and dest modification */
public void setEffort(String val) {
if (val != null) {
@ -904,16 +964,20 @@ public class IndexBean {
I2PTunnelHTTPClientBase.PROP_AUTH, I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH
};
private static final String _booleanServerOpts[] = {
"i2cp.reduceOnIdle", "i2cp.encryptLeaseSet", "i2cp.enableAccessList"
"i2cp.reduceOnIdle", "i2cp.encryptLeaseSet", PROP_ENABLE_ACCESS_LIST, PROP_ENABLE_BLACKLIST
};
private static final String _otherClientOpts[] = {
"i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.closeIdleTime",
"proxyUsername", "proxyPassword", "outproxyUsername", "outproxyPassword"
"proxyUsername", "proxyPassword", "outproxyUsername", "outproxyPassword",
I2PTunnelHTTPClient.PROP_JUMP_SERVERS
};
private static final String _otherServerOpts[] = {
"i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.leaseSetKey", "i2cp.accessList"
"i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.leaseSetKey", "i2cp.accessList",
PROP_MAX_CONNS_MIN, PROP_MAX_CONNS_HOUR, PROP_MAX_CONNS_DAY,
PROP_MAX_TOTAL_CONNS_MIN, PROP_MAX_TOTAL_CONNS_HOUR, PROP_MAX_TOTAL_CONNS_DAY,
PROP_MAX_STREAMS
};
protected static final Set _noShowSet = new HashSet();
protected static final Set _noShowSet = new HashSet(64);
static {
_noShowSet.addAll(Arrays.asList(_noShowOpts));
_noShowSet.addAll(Arrays.asList(_booleanClientOpts));
@ -929,12 +993,14 @@ public class IndexBean {
config.setProperty("name", _name);
if (_description != null)
config.setProperty("description", _description);
if (_i2cpHost != null)
config.setProperty("i2cpHost", _i2cpHost);
if ( (_i2cpPort != null) && (_i2cpPort.trim().length() > 0) ) {
config.setProperty("i2cpPort", _i2cpPort);
} else {
config.setProperty("i2cpPort", "7654");
if (!_context.isRouterContext()) {
if (_i2cpHost != null)
config.setProperty("i2cpHost", _i2cpHost);
if ( (_i2cpPort != null) && (_i2cpPort.trim().length() > 0) ) {
config.setProperty("i2cpPort", _i2cpPort);
} else {
config.setProperty("i2cpPort", "7654");
}
}
if (_privKeyFile != null)
config.setProperty("privKeyFile", _privKeyFile);
@ -1020,7 +1086,7 @@ public class IndexBean {
}
}
private String _(String key) {
protected String _(String key) {
return Messages._(key, _context);
}
}