diff --git a/VERSION.txt b/VERSION.txt index be56aa7a119..d74481b7638 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -10,6 +10,7 @@ jetty-7.0.1-SNAPSHOT + 291543 make bin/*.sh scripts executable in distribution + 291589 Update jetty-rewrite demo + 292642 Fix errors in embedded Jetty examples + + 292825 Continuations ISE rather than ignore bad transitions + JETTY-937 More JVM bug work arounds. Insert pause if all else fails + JETTY-983 Send content-length with multipart ranges + JETTY-1114 unsynchronised WebAppClassloader.getResource(String) @@ -17,7 +18,6 @@ jetty-7.0.1-SNAPSHOT + JETTY-1122 Handle multi-byte utf that causes buffer overflow + JETTY-1125 TransparentProxy incorrectly configured for test webapp + JETTY-1129 Filter control characters out of StdErrLog - + Continuations ISE rather than ignore bad transitions + Fixed XSS issue in CookieDump demo servlet. + Improved start.jar usage text for properties + Promoted Jetty Centralized Logging from Sandbox diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java index 26f28386971..4b0a605b0d0 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java @@ -18,6 +18,7 @@ import java.util.HashSet; import java.util.Queue; import java.util.StringTokenizer; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -35,8 +36,8 @@ import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; import org.eclipse.jetty.continuation.Continuation; +import org.eclipse.jetty.continuation.ContinuationListener; import org.eclipse.jetty.continuation.ContinuationSupport; -import org.eclipse.jetty.util.ArrayQueue; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.thread.Timeout; @@ -133,6 +134,7 @@ public class DoSFilter implements Filter protected boolean _remotePort; protected Semaphore _passes; protected Queue[] _queue; + protected ContinuationListener[] _listener; protected int _maxRequestsPerSec; protected final ConcurrentHashMap _rateTrackers=new ConcurrentHashMap(); @@ -149,8 +151,23 @@ public class DoSFilter implements Filter _context = filterConfig.getServletContext(); _queue = new Queue[getMaxPriority() + 1]; + _listener = new ContinuationListener[getMaxPriority() + 1]; for (int p = 0; p < _queue.length; p++) - _queue[p] = new ArrayQueue(); + { + _queue[p] = new ConcurrentLinkedQueue(); + + final int priority=p; + _listener[p] = new ContinuationListener() + { + public void onComplete(Continuation continuation) + {} + + public void onTimeout(Continuation continuation) + { + _queue[priority].remove(continuation); + } + }; + } int baseRateLimit = __DEFAULT_MAX_REQUESTS_PER_SEC; if (filterConfig.getInitParameter(MAX_REQUESTS_PER_S_INIT_PARAM) != null) @@ -328,7 +345,7 @@ public class DoSFilter implements Filter if (!accepted) { // we were not accepted, so either we suspend to wait,or if we were woken up we insist or we fail - final Continuation continuation = ContinuationSupport.getContinuation(request,response); + final Continuation continuation = ContinuationSupport.getContinuation(request); Boolean throttled = (Boolean)request.getAttribute(__THROTTLED); if (throttled!=Boolean.TRUE && _throttleMs>0) @@ -341,6 +358,7 @@ public class DoSFilter implements Filter continuation.setTimeout(_throttleMs); continuation.suspend(); + continuation.addContinuationListener(_listener[priority]); _queue[priority].add(continuation); return; } @@ -375,17 +393,13 @@ public class DoSFilter implements Filter if (accepted) { // wake up the next highest priority request. - synchronized (_queue) + for (int p = _queue.length; p-- > 0;) { - for (int p = _queue.length; p-- > 0;) + Continuation continuation = _queue[p].poll(); + if (continuation != null && continuation.isSuspended()) { - Continuation continuation = _queue[p].poll(); - - if (continuation != null) - { - continuation.resume(); - break; - } + continuation.resume(); + break; } } _passes.release(); diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/QoSFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/QoSFilter.java index d27173d63be..b9fd81a071c 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/QoSFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/QoSFilter.java @@ -15,6 +15,7 @@ package org.eclipse.jetty.servlets; import java.io.IOException; import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -30,6 +31,7 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.eclipse.jetty.continuation.Continuation; +import org.eclipse.jetty.continuation.ContinuationListener; import org.eclipse.jetty.continuation.ContinuationSupport; import org.eclipse.jetty.util.ArrayQueue; @@ -80,6 +82,7 @@ public class QoSFilter implements Filter long _suspendMs; Semaphore _passes; Queue[] _queue; + ContinuationListener[] _listener; String _suspended="QoSFilter@"+this.hashCode(); public void init(FilterConfig filterConfig) @@ -90,8 +93,23 @@ public class QoSFilter implements Filter if (filterConfig.getInitParameter(MAX_PRIORITY_INIT_PARAM)!=null) max_priority=Integer.parseInt(filterConfig.getInitParameter(MAX_PRIORITY_INIT_PARAM)); _queue=new Queue[max_priority+1]; + _listener = new ContinuationListener[max_priority + 1]; for (int p=0;p<_queue.length;p++) - _queue[p]=new ArrayQueue(); + { + _queue[p]=new ConcurrentLinkedQueue(); + + final int priority=p; + _listener[p] = new ContinuationListener() + { + public void onComplete(Continuation continuation) + {} + + public void onTimeout(Continuation continuation) + { + _queue[priority].remove(continuation); + } + }; + } int passes=__DEFAULT_PASSES; if (filterConfig.getInitParameter(MAX_REQUESTS_INIT_PARAM)!=null) @@ -125,12 +143,12 @@ public class QoSFilter implements Filter else { request.setAttribute(_suspended,Boolean.TRUE); - Continuation continuation = ContinuationSupport.getContinuation(request,response); + int priority = getPriority(request); + Continuation continuation = ContinuationSupport.getContinuation(request); if (_suspendMs>0) continuation.setTimeout(_suspendMs); continuation.suspend(); - - int priority = getPriority(request); + continuation.addContinuationListener(_listener[priority]); _queue[priority].add(continuation); return; } @@ -160,7 +178,6 @@ public class QoSFilter implements Filter accepted = true; } } - if (accepted) { @@ -170,9 +187,6 @@ public class QoSFilter implements Filter { ((HttpServletResponse)response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); } - - - } catch(InterruptedException e) { @@ -186,7 +200,7 @@ public class QoSFilter implements Filter for (int p=_queue.length;p-->0;) { Continuation continutaion=_queue[p].poll(); - if (continutaion!=null) + if (continutaion!=null && continutaion.isSuspended()) { continutaion.resume(); break;