Merged branch 'jetty-9.4.x' into 'master'.

This commit is contained in:
Simone Bordet 2016-05-16 15:14:20 +02:00
commit 201bde8bf2
8 changed files with 136 additions and 54 deletions

View File

@ -141,6 +141,7 @@ public class HTTP2Connection extends AbstractConnection
protected class HTTP2Producer implements ExecutionStrategy.Producer
{
private final Callback fillCallback = new FillCallback();
private ByteBuffer buffer;
@Override
@ -182,7 +183,7 @@ public class HTTP2Connection extends AbstractConnection
if (filled == 0)
{
release();
fillInterested();
getEndPoint().fillInterested(fillCallback);
return null;
}
else if (filled < 0)
@ -205,4 +206,19 @@ public class HTTP2Connection extends AbstractConnection
}
}
}
private class FillCallback implements Callback.NonBlocking
{
@Override
public void succeeded()
{
onFillable();
}
@Override
public void failed(Throwable x)
{
onFillInterestedFailed(x);
}
}
}

View File

@ -84,6 +84,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
private int maxLocalStreams;
private int maxRemoteStreams;
private long streamIdleTimeout;
private int initialSessionRecvWindow;
private boolean pushEnabled;
private long idleTime;
@ -149,6 +150,17 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
this.streamIdleTimeout = streamIdleTimeout;
}
@ManagedAttribute("The initial size of session's flow control receive window")
public int getInitialSessionRecvWindow()
{
return initialSessionRecvWindow;
}
public void setInitialSessionRecvWindow(int initialSessionRecvWindow)
{
this.initialSessionRecvWindow = initialSessionRecvWindow;
}
public EndPoint getEndPoint()
{
return endPoint;

View File

@ -36,6 +36,7 @@ import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.thread.ExecutionStrategy;
import org.eclipse.jetty.util.thread.strategy.ProduceExecuteConsume;
@ManagedObject
public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConnectionFactory
@ -43,11 +44,12 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
private final Connection.Listener connectionListener = new ConnectionListener();
private final HttpConfiguration httpConfiguration;
private int maxDynamicTableSize = 4096;
private int initialStreamSendWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE;
private int initialStreamRecvWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE;
private int initialSessionRecvWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE;
private int maxConcurrentStreams = -1;
private int maxHeaderBlockFragment = 0;
private FlowControlStrategy.Factory flowControlStrategyFactory = () -> new BufferingFlowControlStrategy(0.5F);
private ExecutionStrategy.Factory executionStrategyFactory = ExecutionStrategy.Factory.getDefault();
private ExecutionStrategy.Factory executionStrategyFactory = new ProduceExecuteConsume.Factory();
public AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration)
{
@ -72,15 +74,46 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
this.maxDynamicTableSize = maxDynamicTableSize;
}
@ManagedAttribute("The initial size of stream's flow control send window")
public int getInitialStreamSendWindow()
@ManagedAttribute("The initial size of session's flow control receive window")
public int getInitialSessionRecvWindow()
{
return initialStreamSendWindow;
return initialSessionRecvWindow;
}
public void setInitialSessionRecvWindow(int initialSessionRecvWindow)
{
this.initialSessionRecvWindow = initialSessionRecvWindow;
}
@ManagedAttribute("The initial size of stream's flow control receive window")
public int getInitialStreamRecvWindow()
{
return initialStreamRecvWindow;
}
public void setInitialStreamRecvWindow(int initialStreamRecvWindow)
{
this.initialStreamRecvWindow = initialStreamRecvWindow;
}
/**
* @deprecated use {@link #getInitialStreamRecvWindow()} instead,
* since "send" is meant on the client, but this is the server configuration
*/
@Deprecated
public int getInitialStreamSendWindow()
{
return getInitialStreamRecvWindow();
}
/**
* @deprecated use {@link #setInitialStreamRecvWindow(int)} instead,
* since "send" is meant on the client, but this is the server configuration
*/
@Deprecated
public void setInitialStreamSendWindow(int initialStreamSendWindow)
{
this.initialStreamSendWindow = initialStreamSendWindow;
setInitialStreamRecvWindow(initialStreamSendWindow);
}
@ManagedAttribute("The max number of concurrent streams per session")
@ -144,6 +177,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
// the typical case is that the connection will be busier and the
// stream idle timeout will expire earlier that the connection's.
session.setStreamIdleTimeout(endPoint.getIdleTimeout());
session.setInitialSessionRecvWindow(getInitialSessionRecvWindow());
ServerParser parser = newServerParser(connector, session);
HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(),

View File

@ -184,7 +184,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
upgradeFrames.add(new PrefaceFrame());
upgradeFrames.add(settingsFrame);
// Remember the request to send a response from onOpen().
upgradeFrames.add(new HeadersFrame(1, request, null, true));
upgradeFrames.add(new HeadersFrame(1, new Request(request), null, true));
}
return true;
}

View File

@ -49,7 +49,7 @@ public class HTTP2ServerConnectionFactory extends AbstractHTTP2ServerConnectionF
{
super(httpConfiguration);
}
protected HTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration,String... protocols)
{
super(httpConfiguration,protocols);
@ -93,7 +93,7 @@ public class HTTP2ServerConnectionFactory extends AbstractHTTP2ServerConnectionF
{
Map<Integer, Integer> settings = new HashMap<>();
settings.put(SettingsFrame.HEADER_TABLE_SIZE, getMaxDynamicTableSize());
settings.put(SettingsFrame.INITIAL_WINDOW_SIZE, getInitialStreamSendWindow());
settings.put(SettingsFrame.INITIAL_WINDOW_SIZE, getInitialStreamRecvWindow());
int maxConcurrentStreams = getMaxConcurrentStreams();
if (maxConcurrentStreams >= 0)
settings.put(SettingsFrame.MAX_CONCURRENT_STREAMS, maxConcurrentStreams);

View File

@ -33,6 +33,7 @@ import org.eclipse.jetty.http2.frames.Frame;
import org.eclipse.jetty.http2.frames.HeadersFrame;
import org.eclipse.jetty.http2.frames.PushPromiseFrame;
import org.eclipse.jetty.http2.frames.SettingsFrame;
import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
import org.eclipse.jetty.http2.generator.Generator;
import org.eclipse.jetty.http2.parser.ServerParser;
import org.eclipse.jetty.io.EndPoint;
@ -60,9 +61,17 @@ public class HTTP2ServerSession extends HTTP2Session implements ServerParser.Lis
Map<Integer, Integer> settings = notifyPreface(this);
if (settings == null)
settings = Collections.emptyMap();
SettingsFrame frame = new SettingsFrame(settings, false);
// TODO: consider sending a WINDOW_UPDATE to enlarge the session send window of the client.
frames(null, Callback.NOOP, frame, Frame.EMPTY_ARRAY);
SettingsFrame settingsFrame = new SettingsFrame(settings, false);
WindowUpdateFrame windowFrame = null;
int sessionWindow = getInitialSessionRecvWindow() - FlowControlStrategy.DEFAULT_WINDOW_SIZE;
if (sessionWindow > 0)
windowFrame = new WindowUpdateFrame(0, sessionWindow);
if (windowFrame == null)
frames(null, Callback.NOOP, settingsFrame, Frame.EMPTY_ARRAY);
else
frames(null, Callback.NOOP, settingsFrame, windowFrame);
}
@Override

View File

@ -1,3 +1,4 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
org.eclipse.jetty.http2.hpack.LEVEL=INFO
#org.eclipse.jetty.LEVEL=DEBUG
#org.eclipse.jetty.http2.LEVEL=DEBUG
org.eclipse.jetty.http2.hpack.LEVEL=INFO

View File

@ -41,60 +41,67 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
{
public final static String GLOBAL_ERROR_PAGE = "org.eclipse.jetty.server.error_page.global";
private static final Logger LOG = Log.getLogger(ErrorPageErrorHandler.class);
enum PageLookupTechnique{ THROWABLE, STATUS_CODE, GLOBAL }
private enum PageLookupTechnique
{
THROWABLE, STATUS_CODE, GLOBAL
}
protected ServletContext _servletContext;
private final Map<String,String> _errorPages= new HashMap<>(); // code or exception to URL
private final List<ErrorCodeRange> _errorPageList= new ArrayList<>(); // list of ErrorCode by range
private final Map<String, String> _errorPages = new HashMap<>(); // code or exception to URL
private final List<ErrorCodeRange> _errorPageList = new ArrayList<>(); // list of ErrorCode by range
@Override
public String getErrorPage(HttpServletRequest request)
{
String error_page= null;
String error_page = null;
PageLookupTechnique pageSource = null;
Class<?> matchedThrowable = null;
Throwable th = (Throwable)request.getAttribute(Dispatcher.ERROR_EXCEPTION);
// Walk the cause hierarchy
while (error_page == null && th != null )
while (error_page == null && th != null)
{
pageSource = PageLookupTechnique.THROWABLE;
Class<?> exClass=th.getClass();
Class<?> exClass = th.getClass();
error_page = _errorPages.get(exClass.getName());
// walk the inheritance hierarchy
while (error_page == null)
{
exClass= exClass.getSuperclass();
if (exClass==null)
exClass = exClass.getSuperclass();
if (exClass == null)
break;
error_page=_errorPages.get(exClass.getName());
error_page = _errorPages.get(exClass.getName());
}
th=(th instanceof ServletException)?((ServletException)th).getRootCause():null;
if (error_page != null)
matchedThrowable = exClass;
th = (th instanceof ServletException) ? ((ServletException)th).getRootCause() : null;
}
Integer errorStatusCode = null;
if (error_page == null)
{
pageSource = PageLookupTechnique.STATUS_CODE;
// look for an exact code match
errorStatusCode = (Integer)request.getAttribute(Dispatcher.ERROR_STATUS_CODE);
if (errorStatusCode!=null)
if (errorStatusCode != null)
{
error_page= (String)_errorPages.get(Integer.toString(errorStatusCode));
error_page = _errorPages.get(Integer.toString(errorStatusCode));
// if still not found
if ((error_page == null) && (_errorPageList != null))
if (error_page == null)
{
// look for an error code range match.
for (int i = 0; i < _errorPageList.size(); i++)
for (ErrorCodeRange errCode : _errorPageList)
{
ErrorCodeRange errCode = _errorPageList.get(i);
if (errCode.isInRange(errorStatusCode))
{
error_page = errCode.getUri();
@ -111,7 +118,7 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
pageSource = PageLookupTechnique.GLOBAL;
error_page = _errorPages.get(GLOBAL_ERROR_PAGE);
}
if (LOG.isDebugEnabled())
{
StringBuilder dbg = new StringBuilder();
@ -122,10 +129,13 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
switch (pageSource)
{
case THROWABLE:
dbg.append(" (from Throwable ");
dbg.append(th.getClass().getName());
dbg.append(" (using matched Throwable ");
dbg.append(matchedThrowable.getName());
dbg.append(" / actually thrown as ");
Throwable originalThrowable = (Throwable)request.getAttribute(Dispatcher.ERROR_EXCEPTION);
dbg.append(originalThrowable.getClass().getName());
dbg.append(')');
LOG.debug(dbg.toString(),th);
LOG.debug(dbg.toString(), th);
break;
case STATUS_CODE:
dbg.append(" (from status code ");
@ -143,7 +153,7 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
return error_page;
}
public Map<String,String> getErrorPages()
public Map<String, String> getErrorPages()
{
return _errorPages;
}
@ -151,10 +161,10 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
/**
* @param errorPages a map of Exception class names or error codes as a string to URI string
*/
public void setErrorPages(Map<String,String> errorPages)
public void setErrorPages(Map<String, String> errorPages)
{
_errorPages.clear();
if (errorPages!=null)
if (errorPages != null)
_errorPages.putAll(errorPages);
}
@ -164,11 +174,11 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
* or may be called directly
*
* @param exception The exception
* @param uri The URI of the error page.
* @param uri The URI of the error page.
*/
public void addErrorPage(Class<? extends Throwable> exception,String uri)
public void addErrorPage(Class<? extends Throwable> exception, String uri)
{
_errorPages.put(exception.getName(),uri);
_errorPages.put(exception.getName(), uri);
}
/**
@ -177,11 +187,11 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
* or may be called directly
*
* @param exceptionClassName The exception
* @param uri The URI of the error page.
* @param uri The URI of the error page.
*/
public void addErrorPage(String exceptionClassName,String uri)
public void addErrorPage(String exceptionClassName, String uri)
{
_errorPages.put(exceptionClassName,uri);
_errorPages.put(exceptionClassName, uri);
}
/**
@ -190,11 +200,11 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
* or may be called directly.
*
* @param code The HTTP status code to match
* @param uri The URI of the error page.
* @param uri The URI of the error page.
*/
public void addErrorPage(int code,String uri)
public void addErrorPage(int code, String uri)
{
_errorPages.put(Integer.toString(code),uri);
_errorPages.put(Integer.toString(code), uri);
}
/**
@ -202,8 +212,8 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
* This method is not available from web.xml and must be called directly.
*
* @param from The lowest matching status code
* @param to The highest matching status code
* @param uri The URI of the error page.
* @param to The highest matching status code
* @param uri The URI of the error page.
*/
public void addErrorPage(int from, int to, String uri)
{
@ -214,7 +224,7 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
protected void doStart() throws Exception
{
super.doStart();
_servletContext=ContextHandler.getCurrentContext();
_servletContext = ContextHandler.getCurrentContext();
}
private static class ErrorCodeRange
@ -224,7 +234,7 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
private String _uri;
ErrorCodeRange(int from, int to, String uri)
throws IllegalArgumentException
throws IllegalArgumentException
{
if (from > to)
throw new IllegalArgumentException("from>to");
@ -236,7 +246,7 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
boolean isInRange(int value)
{
return (value >= _from) && (value <= _to);
return _from <= value && value <= _to;
}
String getUri()