forked from I2P_Developers/i2p.i2p
* i2ptunnel:
- Set default read timeout in standard server - Reduce header timeout, enforce total header timeout in IRC and HTTP servers (ticket #723) * Streaming: Don't ignore option or force connect timeout to 5 minutes * Streaming javadocs * SocketTimeout cleanup
This commit is contained in:
@ -45,7 +45,8 @@ 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 static final long HEADER_TIMEOUT = 15*1000;
|
||||
private static final long TOTAL_HEADER_TIMEOUT = 2 * HEADER_TIMEOUT;
|
||||
private static final long START_INTERVAL = (60 * 1000) * 3;
|
||||
private long _startedOn = 0L;
|
||||
|
||||
@ -492,7 +493,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
|
||||
}
|
||||
}
|
||||
|
||||
protected static Map<String, List<String>> readHeaders(InputStream in, StringBuilder command, String[] skipHeaders, I2PAppContext ctx) throws IOException {
|
||||
protected static Map<String, List<String>> readHeaders(InputStream in, StringBuilder command,
|
||||
String[] skipHeaders, I2PAppContext ctx) throws IOException {
|
||||
HashMap<String, List<String>> headers = new HashMap<String, List<String>>();
|
||||
StringBuilder buf = new StringBuilder(128);
|
||||
|
||||
@ -516,6 +518,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
|
||||
if (trimmed > 0)
|
||||
ctx.statManager().addRateData("i2ptunnel.httpNullWorkaround", trimmed, 0);
|
||||
|
||||
// slowloris / darkloris
|
||||
long expire = ctx.clock().now() + TOTAL_HEADER_TIMEOUT;
|
||||
int i = 0;
|
||||
while (true) {
|
||||
if (++i > MAX_HEADERS)
|
||||
@ -528,6 +532,8 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
|
||||
// end of headers reached
|
||||
return headers;
|
||||
} else {
|
||||
if (ctx.clock().now() > expire)
|
||||
throw new IOException("Headers took too long [" + buf.toString() + "]");
|
||||
int split = buf.indexOf(":");
|
||||
if (split <= 0) throw new IOException("Invalid HTTP header, missing colon [" + buf.toString() + "]");
|
||||
String name = buf.substring(0, split).trim();
|
||||
|
@ -62,7 +62,8 @@ 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 long HEADER_TIMEOUT = 60*1000;
|
||||
private static final long HEADER_TIMEOUT = 15*1000;
|
||||
private static final long TOTAL_HEADER_TIMEOUT = 2 * HEADER_TIMEOUT;
|
||||
|
||||
private final static byte[] ERR_UNAVAILABLE =
|
||||
(":ircserver.i2p 499 you :" +
|
||||
@ -188,12 +189,16 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
|
||||
StringBuilder buf = new StringBuilder(128);
|
||||
int lineCount = 0;
|
||||
|
||||
// slowloris / darkloris
|
||||
long expire = System.currentTimeMillis() + TOTAL_HEADER_TIMEOUT;
|
||||
while (true) {
|
||||
String s = DataHelper.readLine(in);
|
||||
if (s == null)
|
||||
throw new IOException("EOF reached before the end of the headers [" + buf.toString() + "]");
|
||||
if (++lineCount > 10)
|
||||
throw new IOException("Too many lines before USER or SERVER, giving up");
|
||||
if (System.currentTimeMillis() > expire)
|
||||
throw new IOException("Headers took too long [" + buf.toString() + "]");
|
||||
s = s.trim();
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("Got line: " + s);
|
||||
|
@ -49,8 +49,8 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
|
||||
protected Logging l;
|
||||
|
||||
private static final long DEFAULT_READ_TIMEOUT = -1; // 3*60*1000;
|
||||
/** default timeout to 3 minutes - override if desired */
|
||||
private static final long DEFAULT_READ_TIMEOUT = 5*60*1000;
|
||||
/** default timeout to 5 minutes - override if desired */
|
||||
protected long readTimeout = DEFAULT_READ_TIMEOUT;
|
||||
|
||||
/** do we use threads? default true (ignored for standard servers, always false) */
|
||||
|
@ -17,6 +17,9 @@ public interface I2PSocketOptions {
|
||||
/**
|
||||
* How long we will wait for the ACK from a SYN, in milliseconds.
|
||||
*
|
||||
* Default 60 seconds. Max of 2 minutes enforced in Connection.java,
|
||||
* and it also interprets <= 0 as default.
|
||||
*
|
||||
* @return milliseconds to wait, or -1 if we will wait indefinitely
|
||||
*/
|
||||
public long getConnectTimeout();
|
||||
@ -24,6 +27,9 @@ public interface I2PSocketOptions {
|
||||
/**
|
||||
* Define how long we will wait for the ACK from a SYN, in milliseconds.
|
||||
*
|
||||
* Default 60 seconds. Max of 2 minutes enforced in Connection.java,
|
||||
* and it also interprets <= 0 as default.
|
||||
*
|
||||
* @param ms timeout in ms
|
||||
*/
|
||||
public void setConnectTimeout(long ms);
|
||||
@ -32,6 +38,9 @@ public interface I2PSocketOptions {
|
||||
* What is the longest we'll block on the input stream while waiting
|
||||
* for more data. If this value is exceeded, the read() throws
|
||||
* InterruptedIOException
|
||||
*
|
||||
* WARNING: Default -1 (unlimited), which is probably not what you want.
|
||||
*
|
||||
* @return timeout in ms
|
||||
*/
|
||||
public long getReadTimeout();
|
||||
@ -40,6 +49,9 @@ public interface I2PSocketOptions {
|
||||
* What is the longest we'll block on the input stream while waiting
|
||||
* for more data. If this value is exceeded, the read() throws
|
||||
* InterruptedIOException
|
||||
*
|
||||
* WARNING: Default -1 (unlimited), which is probably not what you want.
|
||||
*
|
||||
* @param ms timeout in ms
|
||||
*/
|
||||
public void setReadTimeout(long ms);
|
||||
@ -50,6 +62,8 @@ public interface I2PSocketOptions {
|
||||
* either some data is removed or the connection is closed. If this is
|
||||
* less than or equal to zero, there is no limit (warning: can eat ram)
|
||||
*
|
||||
* Default 64 KB
|
||||
*
|
||||
* @return buffer size limit, in bytes
|
||||
*/
|
||||
public int getMaxBufferSize();
|
||||
@ -60,6 +74,8 @@ public interface I2PSocketOptions {
|
||||
* either some data is removed or the connection is closed. If this is
|
||||
* less than or equal to zero, there is no limit (warning: can eat ram)
|
||||
*
|
||||
* Default 64 KB
|
||||
*
|
||||
* @param numBytes How much data will we accept that hasn't been written out yet.
|
||||
*/
|
||||
public void setMaxBufferSize(int numBytes);
|
||||
@ -69,6 +85,9 @@ public interface I2PSocketOptions {
|
||||
* for the data to flush. If this value is exceeded, the write() throws
|
||||
* InterruptedIOException. If this is less than or equal to zero, there
|
||||
* is no timeout.
|
||||
*
|
||||
* Default -1 (unlimited)
|
||||
*
|
||||
* @return wait time to block on the output stream while waiting for the data to flush.
|
||||
*/
|
||||
public long getWriteTimeout();
|
||||
@ -78,6 +97,9 @@ public interface I2PSocketOptions {
|
||||
* for the data to flush. If this value is exceeded, the write() throws
|
||||
* InterruptedIOException. If this is less than or equal to zero, there
|
||||
* is no timeout.
|
||||
*
|
||||
* Default -1 (unlimited)
|
||||
*
|
||||
* @param ms wait time to block on the output stream while waiting for the data to flush.
|
||||
*/
|
||||
public void setWriteTimeout(long ms);
|
||||
|
@ -96,6 +96,9 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
|
||||
/**
|
||||
* How long we will wait for the ACK from a SYN, in milliseconds.
|
||||
*
|
||||
* Default 60 seconds. Max of 2 minutes enforced in Connection.java,
|
||||
* and it also interprets <= 0 as default.
|
||||
*
|
||||
* @return milliseconds to wait, or -1 if we will wait indefinitely
|
||||
*/
|
||||
public long getConnectTimeout() {
|
||||
@ -105,6 +108,9 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
|
||||
/**
|
||||
* Define how long we will wait for the ACK from a SYN, in milliseconds.
|
||||
*
|
||||
* Default 60 seconds. Max of 2 minutes enforced in Connection.java,
|
||||
* and it also interprets <= 0 as default.
|
||||
*
|
||||
*/
|
||||
public void setConnectTimeout(long ms) {
|
||||
_connectTimeout = ms;
|
||||
@ -114,6 +120,8 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
|
||||
* What is the longest we'll block on the input stream while waiting
|
||||
* for more data. If this value is exceeded, the read() throws
|
||||
* InterruptedIOException
|
||||
*
|
||||
* WARNING: Default -1 (unlimited), which is probably not what you want.
|
||||
*/
|
||||
public long getReadTimeout() {
|
||||
return _readTimeout;
|
||||
@ -123,6 +131,8 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
|
||||
* What is the longest we'll block on the input stream while waiting
|
||||
* for more data. If this value is exceeded, the read() throws
|
||||
* InterruptedIOException
|
||||
*
|
||||
* WARNING: Default -1 (unlimited), which is probably not what you want.
|
||||
*/
|
||||
public void setReadTimeout(long ms) {
|
||||
_readTimeout = ms;
|
||||
@ -134,6 +144,8 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
|
||||
* either some data is removed or the connection is closed. If this is
|
||||
* less than or equal to zero, there is no limit (warning: can eat ram)
|
||||
*
|
||||
* Default 64 KB
|
||||
*
|
||||
* @return buffer size limit, in bytes
|
||||
*/
|
||||
public int getMaxBufferSize() {
|
||||
@ -146,6 +158,8 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
|
||||
* either some data is removed or the connection is closed. If this is
|
||||
* less than or equal to zero, there is no limit (warning: can eat ram)
|
||||
*
|
||||
* Default 64 KB
|
||||
*
|
||||
*/
|
||||
public void setMaxBufferSize(int numBytes) {
|
||||
_maxBufferSize = numBytes;
|
||||
@ -156,6 +170,8 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
|
||||
* for the data to flush. If this value is exceeded, the write() throws
|
||||
* InterruptedIOException. If this is less than or equal to zero, there
|
||||
* is no timeout.
|
||||
*
|
||||
* Default -1 (unlimited)
|
||||
*/
|
||||
public long getWriteTimeout() {
|
||||
return _writeTimeout;
|
||||
@ -166,6 +182,8 @@ class I2PSocketOptionsImpl implements I2PSocketOptions {
|
||||
* for the data to flush. If this value is exceeded, the write() throws
|
||||
* InterruptedIOException. If this is less than or equal to zero, there
|
||||
* is no timeout.
|
||||
*
|
||||
* Default -1 (unlimited)
|
||||
*/
|
||||
public void setWriteTimeout(long ms) {
|
||||
_writeTimeout = ms;
|
||||
|
@ -87,7 +87,7 @@ class Connection {
|
||||
/** wait up to 5 minutes after disconnection so we can ack/close packets */
|
||||
public static final int DISCONNECT_TIMEOUT = 5*60*1000;
|
||||
|
||||
private static final long DEFAULT_CONNECT_TIMEOUT = 60*1000;
|
||||
public static final int DEFAULT_CONNECT_TIMEOUT = 60*1000;
|
||||
private static final long MAX_CONNECT_TIMEOUT = 2*60*1000;
|
||||
|
||||
public static final int MAX_WINDOW_SIZE = 128;
|
||||
@ -549,7 +549,15 @@ class Connection {
|
||||
|
||||
public void setInbound() { _isInbound = true; }
|
||||
public boolean isInbound() { return _isInbound; }
|
||||
|
||||
/**
|
||||
* Always true at the start, even if we haven't gotten a reply on an
|
||||
* outbound connection. Only set to false on disconnect.
|
||||
* For outbound, use getHighestAckedThrough() >= 0 also,
|
||||
* to determine if the connection is up.
|
||||
*/
|
||||
public boolean getIsConnected() { return _connected; }
|
||||
|
||||
public boolean getHardDisconnected() { return _hardDisconnected; }
|
||||
public boolean getResetSent() { return _resetSent; }
|
||||
public long getResetSentOn() { return _resetSentOn; }
|
||||
@ -1017,7 +1025,7 @@ class Connection {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder(128);
|
||||
StringBuilder buf = new StringBuilder(256);
|
||||
buf.append("[Connection ");
|
||||
if (_receiveStreamId > 0)
|
||||
buf.append(Packet.toId(_receiveStreamId));
|
||||
@ -1075,6 +1083,7 @@ class Connection {
|
||||
buf.append(" close received ").append(DataHelper.formatDuration(_context.clock().now() - getCloseReceivedOn())).append(" ago");
|
||||
buf.append(" sent: ").append(1 + _lastSendId.get());
|
||||
buf.append(" rcvd: ").append(1 + _inputStream.getHighestBlockId() - missing);
|
||||
buf.append(" ackThru ").append(_highestAckedThrough);
|
||||
|
||||
buf.append(" maxWin ").append(getOptions().getMaxWindowSize());
|
||||
buf.append(" MTU ").append(getOptions().getMaxMessageSize());
|
||||
|
@ -343,8 +343,8 @@ class ConnectionOptions extends I2PSocketOptionsImpl {
|
||||
DEFAULT_CONGESTION_AVOIDANCE_GROWTH_RATE_FACTOR));
|
||||
setSlowStartGrowthRateFactor(getInt(opts, PROP_SLOW_START_GROWTH_RATE_FACTOR,
|
||||
DEFAULT_SLOW_START_GROWTH_RATE_FACTOR));
|
||||
// overrides default in super()
|
||||
setConnectTimeout(getInt(opts, PROP_CONNECT_TIMEOUT, Connection.DISCONNECT_TIMEOUT));
|
||||
// overrides default in super()... why?
|
||||
//setConnectTimeout(getInt(opts, PROP_CONNECT_TIMEOUT, Connection.DISCONNECT_TIMEOUT));
|
||||
setAnswerPings(getBool(opts, PROP_ANSWER_PINGS, DEFAULT_ANSWER_PINGS));
|
||||
setEnforceProtocol(getBool(opts, PROP_ENFORCE_PROTO, DEFAULT_ENFORCE_PROTO));
|
||||
initLists(opts);
|
||||
@ -399,9 +399,8 @@ class ConnectionOptions extends I2PSocketOptionsImpl {
|
||||
setSlowStartGrowthRateFactor(getInt(opts, PROP_SLOW_START_GROWTH_RATE_FACTOR,
|
||||
DEFAULT_SLOW_START_GROWTH_RATE_FACTOR));
|
||||
if (opts.containsKey(PROP_CONNECT_TIMEOUT))
|
||||
// wow 5 minutes!!! FIXME!!
|
||||
// overrides default in super()
|
||||
setConnectTimeout(getInt(opts, PROP_CONNECT_TIMEOUT, Connection.DISCONNECT_TIMEOUT));
|
||||
setConnectTimeout(getInt(opts, PROP_CONNECT_TIMEOUT, Connection.DEFAULT_CONNECT_TIMEOUT));
|
||||
if (opts.containsKey(PROP_ANSWER_PINGS))
|
||||
setAnswerPings(getBool(opts, PROP_ANSWER_PINGS, DEFAULT_ANSWER_PINGS));
|
||||
if (opts.containsKey(PROP_ENFORCE_PROTO))
|
||||
|
@ -29,7 +29,7 @@ class SchedulerChooser {
|
||||
TaskScheduler scheduler = _schedulers.get(i);
|
||||
if (scheduler.accept(con)) {
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("Scheduling for " + con + " with " + scheduler.getClass().getName());
|
||||
// _log.debug("Scheduling for " + con + " with " + scheduler.getClass().getSimpleName());
|
||||
return scheduler;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import java.util.Date;
|
||||
|
||||
/**
|
||||
* This should be deprecated.
|
||||
* It is only used by EepGet, and it uses the inefficient SimpleTimer.
|
||||
* It is only used by EepGet.
|
||||
* The only advantage seems to be a total timeout period, which is the second
|
||||
* argument to EepGet.fetch(headerTimeout, totalTimeout, inactivityTimeout),
|
||||
* which is most likely always set to -1.
|
||||
@ -15,14 +15,16 @@ import java.util.Date;
|
||||
* Use socket.setsotimeout instead?
|
||||
*/
|
||||
public class SocketTimeout extends SimpleTimer2.TimedEvent {
|
||||
private Socket _targetSocket;
|
||||
private long _startTime;
|
||||
private long _inactivityDelay;
|
||||
private long _lastActivity;
|
||||
private long _totalTimeoutTime;
|
||||
private boolean _cancelled;
|
||||
private Runnable _command;
|
||||
private volatile Socket _targetSocket;
|
||||
private final long _startTime;
|
||||
private volatile long _inactivityDelay;
|
||||
private volatile long _lastActivity;
|
||||
private volatile long _totalTimeoutTime;
|
||||
private volatile boolean _cancelled;
|
||||
private volatile Runnable _command;
|
||||
|
||||
public SocketTimeout(long delay) { this(null, delay); }
|
||||
|
||||
public SocketTimeout(Socket socket, long delay) {
|
||||
super(SimpleTimer2.getInstance());
|
||||
_inactivityDelay = delay;
|
||||
@ -32,6 +34,7 @@ public class SocketTimeout extends SimpleTimer2.TimedEvent {
|
||||
_totalTimeoutTime = -1;
|
||||
schedule(delay);
|
||||
}
|
||||
|
||||
public void timeReached() {
|
||||
if (_cancelled) return;
|
||||
|
||||
@ -53,23 +56,27 @@ public class SocketTimeout extends SimpleTimer2.TimedEvent {
|
||||
_cancelled = true;
|
||||
return super.cancel();
|
||||
}
|
||||
|
||||
public void setSocket(Socket s) { _targetSocket = s; }
|
||||
public void resetTimer() { _lastActivity = System.currentTimeMillis(); }
|
||||
public void setInactivityTimeout(long timeout) { _inactivityDelay = timeout; }
|
||||
|
||||
public void setTotalTimeoutPeriod(long timeoutPeriod) {
|
||||
if (timeoutPeriod > 0)
|
||||
_totalTimeoutTime = _startTime + timeoutPeriod;
|
||||
else
|
||||
_totalTimeoutTime = -1;
|
||||
}
|
||||
|
||||
public void setTimeoutCommand(Runnable job) { _command = job; }
|
||||
|
||||
private static final SimpleDateFormat _fmt = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss.SSS");
|
||||
private static String ts(long when) { synchronized (_fmt) { return _fmt.format(new Date(when)); } }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("started on ");
|
||||
buf.append("SocketTimeout started on ");
|
||||
buf.append(ts(_startTime));
|
||||
buf.append(" idle for ");
|
||||
buf.append(System.currentTimeMillis() - _lastActivity);
|
||||
|
12
history.txt
12
history.txt
@ -1,3 +1,15 @@
|
||||
2012-10-07 zzz
|
||||
* I2PAppContext: Improved synching in constructor
|
||||
* i2ptunnel:
|
||||
- Set default read timeout in standard server
|
||||
- Reduce header timeout, enforce total header timeout
|
||||
in IRC and HTTP servers (ticket #723)
|
||||
* Logs:
|
||||
- Flush buffers in logs.jsp
|
||||
- Add dup message to buffers, was in file only
|
||||
* Streaming: Don't ignore option or force connect timeout to 5 minutes
|
||||
* UPnP: Workaround NPE (ticket #728)
|
||||
|
||||
2012-10-06 zzz
|
||||
* configlogging.jsp: Fix IAE
|
||||
* error500.jsp: Fix whitespace
|
||||
|
@ -18,7 +18,7 @@ public class RouterVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Monotone";
|
||||
public final static String VERSION = CoreVersion.VERSION;
|
||||
public final static long BUILD = 10;
|
||||
public final static long BUILD = 11;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
Reference in New Issue
Block a user