Merged branch 'jetty-8'.

This commit is contained in:
Simone Bordet 2013-02-27 18:29:26 +01:00
parent 9ec88ef1c9
commit 849398d840
3 changed files with 35 additions and 151 deletions

View File

@ -85,20 +85,14 @@
<scope>provided</scope>
</dependency>
<dependency>
<<<<<<< HEAD
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
=======
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jmx</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>test-jetty-servlet</artifactId>
<version>${project.version}</version>
>>>>>>> jetty-8
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@ -19,13 +19,9 @@
package org.eclipse.jetty.servlets;
import java.io.IOException;
<<<<<<< HEAD
import java.util.HashSet;
=======
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
>>>>>>> jetty-8
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
@ -55,6 +51,8 @@ import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.ManagedOperation;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Timeout;
@ -118,26 +116,16 @@ import org.eclipse.jetty.util.thread.Timeout;
* <dd>if true and session tracking is not used, then rate is tracked by IP+port (effectively connection). Defaults to false.</dd>
* <p/>
* <dt>ipWhitelist</dt>
<<<<<<< HEAD
* <dd>a comma-separated list of IP addresses that will not be rate limited</dd>
*
* <dt>managedAttr</dt>
* <dd>if set to true, then this servlet is set as a {@link ServletContext} attribute with the
=======
* <dd>a comma-separated list of IP addresses that will not be rate limited</dd>
* <p/>
* <dt>managedAttr</dt>
* <dd>if set to true, then this servlet is set as a {@link ServletContext} attribute with the
>>>>>>> jetty-8
* filter name as the attribute name. This allows context external mechanism (eg JMX via {@link ContextHandler#MANAGED_ATTRIBUTES}) to
* manage the configuration of the filter.</dd>
* </dl>
* </p>
*/
<<<<<<< HEAD
@ManagedObject("limits exposure to abuse from request flooding, whether malicious, or as a result of a misconfigured client")
=======
>>>>>>> jetty-8
public class DoSFilter implements Filter
{
private static final Logger LOG = Log.getLogger(DoSFilter.class);
@ -190,8 +178,8 @@ public class DoSFilter implements Filter
private volatile int _maxRequestsPerSec;
private Queue<Continuation>[] _queue;
private ContinuationListener[] _listeners;
private final ConcurrentHashMap<String, RateTracker> _rateTrackers = new ConcurrentHashMap<String, RateTracker>();
private final List<String> _whitelist = new CopyOnWriteArrayList<String>();
private final ConcurrentHashMap<String, RateTracker> _rateTrackers = new ConcurrentHashMap<>();
private final List<String> _whitelist = new CopyOnWriteArrayList<>();
private final Timeout _requestTimeoutQ = new Timeout();
private final Timeout _trackerTimeoutQ = new Timeout();
private Thread _timerThread;
@ -205,7 +193,7 @@ public class DoSFilter implements Filter
_listeners = new ContinuationListener[getMaxPriority() + 1];
for (int p = 0; p < _queue.length; p++)
{
_queue[p] = new ConcurrentLinkedQueue<Continuation>();
_queue[p] = new ConcurrentLinkedQueue<>();
final int priority = p;
_listeners[p] = new ContinuationListener()
@ -370,26 +358,15 @@ public class DoSFilter implements Filter
case -1:
{
// Reject this request
<<<<<<< HEAD
if (_insertHeaders)
((HttpServletResponse)response).addHeader("DoSFilter","unavailable");
((HttpServletResponse)response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
=======
if (insertHeaders)
response.addHeader("DoSFilter", "unavailable");
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
>>>>>>> jetty-8
return;
}
case 0:
{
// fall through to throttle code
<<<<<<< HEAD
request.setAttribute(__TRACKER,tracker);
=======
request.setAttribute(__TRACKER, tracker);
>>>>>>> jetty-8
break;
}
default:
@ -398,26 +375,9 @@ public class DoSFilter implements Filter
if (insertHeaders)
response.addHeader("DoSFilter", "delayed");
Continuation continuation = ContinuationSupport.getContinuation(request);
<<<<<<< HEAD
request.setAttribute(__TRACKER,tracker);
if (_delayMs > 0)
continuation.setTimeout(_delayMs);
continuation.addContinuationListener(new ContinuationListener()
{
public void onComplete(Continuation continuation)
{
}
public void onTimeout(Continuation continuation)
{
}
});
=======
request.setAttribute(__TRACKER, tracker);
if (delayMs > 0)
continuation.setTimeout(delayMs);
>>>>>>> jetty-8
continuation.suspend();
return;
}
@ -713,23 +673,6 @@ public class DoSFilter implements Filter
}
/**
<<<<<<< HEAD
* Initialize the IP address whitelist
*/
protected void initWhitelist()
{
_whitelist.clear();
StringTokenizer tokenizer = new StringTokenizer(_whitelistStr, ",");
while (tokenizer.hasMoreTokens())
_whitelist.add(tokenizer.nextToken().trim());
LOG.info("Whitelisted IP addresses: {}", _whitelist.toString());
}
/* ------------------------------------------------------------ */
/**
=======
>>>>>>> jetty-8
* Get maximum number of requests from a connection per
* second. Requests in excess of this are first delayed,
* then throttled.
@ -742,10 +685,6 @@ public class DoSFilter implements Filter
return _maxRequestsPerSec;
}
<<<<<<< HEAD
/* ------------------------------------------------------------ */
=======
>>>>>>> jetty-8
/**
* Get maximum number of requests from a connection per
* second. Requests in excess of this are first delayed,
@ -758,10 +697,6 @@ public class DoSFilter implements Filter
_maxRequestsPerSec = value;
}
<<<<<<< HEAD
/* ------------------------------------------------------------ */
=======
>>>>>>> jetty-8
/**
* Get delay (in milliseconds) that is applied to all requests
* over the rate limit, before they are considered at all.
@ -783,10 +718,6 @@ public class DoSFilter implements Filter
_delayMs = value;
}
<<<<<<< HEAD
/* ------------------------------------------------------------ */
=======
>>>>>>> jetty-8
/**
* Get maximum amount of time (in milliseconds) the filter will
* blocking wait for the throttle semaphore.
@ -799,10 +730,6 @@ public class DoSFilter implements Filter
return _maxWaitMs;
}
<<<<<<< HEAD
/* ------------------------------------------------------------ */
=======
>>>>>>> jetty-8
/**
* Set maximum amount of time (in milliseconds) the filter will
* blocking wait for the throttle semaphore.
@ -860,10 +787,6 @@ public class DoSFilter implements Filter
_throttleMs = value;
}
<<<<<<< HEAD
/* ------------------------------------------------------------ */
=======
>>>>>>> jetty-8
/**
* Get maximum amount of time (in milliseconds) to allow
* the request to process.
@ -876,10 +799,6 @@ public class DoSFilter implements Filter
return _maxRequestMs;
}
<<<<<<< HEAD
/* ------------------------------------------------------------ */
=======
>>>>>>> jetty-8
/**
* Set maximum amount of time (in milliseconds) to allow
* the request to process.
@ -904,10 +823,6 @@ public class DoSFilter implements Filter
return _maxIdleTrackerMs;
}
<<<<<<< HEAD
/* ------------------------------------------------------------ */
=======
>>>>>>> jetty-8
/**
* Set maximum amount of time (in milliseconds) to keep track
* of request rates for a connection, before deciding that
@ -920,10 +835,6 @@ public class DoSFilter implements Filter
_maxIdleTrackerMs = value;
}
<<<<<<< HEAD
/* ------------------------------------------------------------ */
=======
>>>>>>> jetty-8
/**
* Check flag to insert the DoSFilter headers into the response.
*
@ -935,10 +846,6 @@ public class DoSFilter implements Filter
return _insertHeaders;
}
<<<<<<< HEAD
/* ------------------------------------------------------------ */
=======
>>>>>>> jetty-8
/**
* Set flag to insert the DoSFilter headers into the response.
*
@ -949,10 +856,6 @@ public class DoSFilter implements Filter
_insertHeaders = value;
}
<<<<<<< HEAD
/* ------------------------------------------------------------ */
=======
>>>>>>> jetty-8
/**
* Get flag to have usage rate tracked by session if a session exists.
*
@ -964,10 +867,6 @@ public class DoSFilter implements Filter
return _trackSessions;
}
<<<<<<< HEAD
/* ------------------------------------------------------------ */
=======
>>>>>>> jetty-8
/**
* Set flag to have usage rate tracked by session if a session exists.
*
@ -978,10 +877,6 @@ public class DoSFilter implements Filter
_trackSessions = value;
}
<<<<<<< HEAD
/* ------------------------------------------------------------ */
=======
>>>>>>> jetty-8
/**
* Get flag to have usage rate tracked by IP+port (effectively connection)
* if session tracking is not used.
@ -994,11 +889,6 @@ public class DoSFilter implements Filter
return _remotePort;
}
<<<<<<< HEAD
/* ------------------------------------------------------------ */
=======
>>>>>>> jetty-8
/**
* Set flag to have usage rate tracked by IP+port (effectively connection)
* if session tracking is not used.
@ -1013,6 +903,7 @@ public class DoSFilter implements Filter
/**
* @return whether this filter is enabled
*/
@ManagedAttribute("whether this filter is enabled")
public boolean isEnabled()
{
return _enabled;
@ -1052,20 +943,33 @@ public class DoSFilter implements Filter
*/
public void setWhitelist(String value)
{
List<String> result = new ArrayList<String>();
List<String> result = new ArrayList<>();
for (String address : value.split(","))
addWhitelistAddress(result, address);
_whitelist.clear();
clearWhitelist();
_whitelist.addAll(result);
LOG.debug("Whitelisted IP addresses: {}", result);
}
/**
* Clears the list of whitelisted IP addresses
*/
@ManagedOperation("clears the list of IP addresses that will not be rate limited")
public void clearWhitelist()
{
_whitelist.clear();
}
public boolean addWhitelistAddress(String address)
/**
* Adds the given IP address, either in the form of a dotted decimal notation A.B.C.D
* or in the CIDR notation A.B.C.D/M, to the list of whitelisted IP addresses.
*
* @param address the address to add
* @return whether the address was added to the list
* @see #removeWhitelistAddress(String)
*/
@ManagedOperation("adds an IP address that will not be rate limited")
public boolean addWhitelistAddress(@Name("address") String address)
{
return addWhitelistAddress(_whitelist, address);
}
@ -1083,6 +987,14 @@ public class DoSFilter implements Filter
return false;
}
/**
* Removes the given address from the list of whitelisted IP addresses.
*
* @param address the address to remove
* @return whether the address was removed from the list
* @see #addWhitelistAddress(List, String)
*/
@ManagedOperation("removes an IP address that will not be rate limited")
public boolean removeWhitelistAddress(String address)
{
return _whitelist.remove(address);
@ -1099,12 +1011,7 @@ public class DoSFilter implements Filter
transient protected final long[] _timestamps;
transient protected int _next;
<<<<<<< HEAD
public RateTracker(String id, int type,int maxRequestsPerSecond)
=======
public RateTracker(String id, int type, int maxRequestsPerSecond)
>>>>>>> jetty-8
{
_id = id;
_type = type;
@ -1147,15 +1054,9 @@ public class DoSFilter implements Filter
public void valueUnbound(HttpSessionBindingEvent event)
{
//take the tracker out of the list of trackers
<<<<<<< HEAD
if (_rateTrackers != null)
_rateTrackers.remove(_id);
if (LOG.isDebugEnabled()) LOG.debug("Tracker removed: "+_id);
=======
_rateTrackers.remove(_id);
if (LOG.isDebugEnabled())
LOG.debug("Tracker removed: {}", getId());
>>>>>>> jetty-8
}
public void sessionWillPassivate(HttpSessionEvent se)
@ -1172,10 +1073,6 @@ public class DoSFilter implements Filter
LOG.warn("Unexpected session activation");
}
<<<<<<< HEAD
=======
>>>>>>> jetty-8
public void expired()
{
long now = _trackerTimeoutQ.getNow();
@ -1194,11 +1091,6 @@ public class DoSFilter implements Filter
{
return "RateTracker/" + _id + "/" + _type;
}
<<<<<<< HEAD
=======
>>>>>>> jetty-8
}
class FixedRateTracker extends RateTracker

View File

@ -24,12 +24,12 @@ import java.util.Set;
import javax.management.Attribute;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.servlet.DispatcherType;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.junit.Assert;
@ -41,8 +41,7 @@ public class DoSFilterJMXTest
public void testDoSFilterJMX() throws Exception
{
Server server = new Server();
Connector connector = new SelectChannelConnector();
connector.setPort(0);
Connector connector = new ServerConnector(server);
server.addConnector(connector);
ServletContextHandler context = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS);
@ -57,7 +56,6 @@ public class DoSFilterJMXTest
MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
MBeanContainer mbeanContainer = new MBeanContainer(mbeanServer);
server.addBean(mbeanContainer);
server.getContainer().addEventListener(mbeanContainer);
server.start();