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

This commit is contained in:
Simone Bordet 2015-12-23 11:26:11 +01:00
commit 802948259e
10 changed files with 210 additions and 53 deletions

View File

@ -30,6 +30,7 @@ import java.util.Map;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import org.eclipse.jetty.alpn.client.ALPNClientConnectionFactory; import org.eclipse.jetty.alpn.client.ALPNClientConnectionFactory;
import org.eclipse.jetty.http2.FlowControlStrategy;
import org.eclipse.jetty.http2.api.Session; import org.eclipse.jetty.http2.api.Session;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.ClientConnectionFactory; import org.eclipse.jetty.io.ClientConnectionFactory;
@ -41,6 +42,8 @@ import org.eclipse.jetty.io.SelectorManager;
import org.eclipse.jetty.io.SocketChannelEndPoint; import org.eclipse.jetty.io.SocketChannelEndPoint;
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory; import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
import org.eclipse.jetty.util.Promise; import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle; import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.QueuedThreadPool;
@ -107,6 +110,7 @@ import org.eclipse.jetty.util.thread.Scheduler;
* client.stop(); * client.stop();
* </pre> * </pre>
*/ */
@ManagedObject
public class HTTP2Client extends ContainerLifeCycle public class HTTP2Client extends ContainerLifeCycle
{ {
private Executor executor; private Executor executor;
@ -117,7 +121,10 @@ public class HTTP2Client extends ContainerLifeCycle
private int selectors = 1; private int selectors = 1;
private long idleTimeout = 30000; private long idleTimeout = 30000;
private long connectTimeout = 10000; private long connectTimeout = 10000;
private int inputBufferSize = 8192;
private List<String> protocols = Arrays.asList("h2", "h2-17", "h2-16", "h2-15", "h2-14"); private List<String> protocols = Arrays.asList("h2", "h2-17", "h2-16", "h2-15", "h2-14");
private int initialSessionRecvWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE;
private int initialStreamRecvWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE;
@Override @Override
protected void doStart() throws Exception protected void doStart() throws Exception
@ -134,13 +141,15 @@ public class HTTP2Client extends ContainerLifeCycle
if (connectionFactory == null) if (connectionFactory == null)
{ {
HTTP2ClientConnectionFactory h2 = new HTTP2ClientConnectionFactory(); HTTP2ClientConnectionFactory h2 = new HTTP2ClientConnectionFactory();
ALPNClientConnectionFactory alpn = new ALPNClientConnectionFactory(getExecutor(), h2, getProtocols());
setClientConnectionFactory((endPoint, context) -> setClientConnectionFactory((endPoint, context) ->
{ {
ClientConnectionFactory factory = h2; ClientConnectionFactory factory = h2;
SslContextFactory sslContextFactory = (SslContextFactory)context.get(SslClientConnectionFactory.SSL_CONTEXT_FACTORY_CONTEXT_KEY); SslContextFactory sslContextFactory = (SslContextFactory)context.get(SslClientConnectionFactory.SSL_CONTEXT_FACTORY_CONTEXT_KEY);
if (sslContextFactory != null) if (sslContextFactory != null)
{
ALPNClientConnectionFactory alpn = new ALPNClientConnectionFactory(getExecutor(), h2, getProtocols());
factory = new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), alpn); factory = new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), alpn);
}
return factory.newConnection(endPoint, context); return factory.newConnection(endPoint, context);
}); });
} }
@ -204,6 +213,7 @@ public class HTTP2Client extends ContainerLifeCycle
this.connectionFactory = connectionFactory; this.connectionFactory = connectionFactory;
} }
@ManagedAttribute("The number of selectors")
public int getSelectors() public int getSelectors()
{ {
return selectors; return selectors;
@ -214,6 +224,7 @@ public class HTTP2Client extends ContainerLifeCycle
this.selectors = selectors; this.selectors = selectors;
} }
@ManagedAttribute("The idle timeout in milliseconds")
public long getIdleTimeout() public long getIdleTimeout()
{ {
return idleTimeout; return idleTimeout;
@ -224,6 +235,7 @@ public class HTTP2Client extends ContainerLifeCycle
this.idleTimeout = idleTimeout; this.idleTimeout = idleTimeout;
} }
@ManagedAttribute("The connect timeout in milliseconds")
public long getConnectTimeout() public long getConnectTimeout()
{ {
return connectTimeout; return connectTimeout;
@ -237,6 +249,18 @@ public class HTTP2Client extends ContainerLifeCycle
selector.setConnectTimeout(connectTimeout); selector.setConnectTimeout(connectTimeout);
} }
@ManagedAttribute("The size of the buffer used to read from the network")
public int getInputBufferSize()
{
return inputBufferSize;
}
public void setInputBufferSize(int inputBufferSize)
{
this.inputBufferSize = inputBufferSize;
}
@ManagedAttribute("The ALPN protocol list")
public List<String> getProtocols() public List<String> getProtocols()
{ {
return protocols; return protocols;
@ -247,6 +271,28 @@ public class HTTP2Client extends ContainerLifeCycle
this.protocols = protocols; this.protocols = protocols;
} }
@ManagedAttribute("The initial size of session's flow control receive window")
public int getInitialSessionRecvWindow()
{
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;
}
public void connect(InetSocketAddress address, Session.Listener listener, Promise<Session> promise) public void connect(InetSocketAddress address, Session.Listener listener, Promise<Session> promise)
{ {
connect(null, address, listener, promise); connect(null, address, listener, promise);

View File

@ -39,6 +39,7 @@ import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Promise; import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.Scheduler;
public class HTTP2ClientConnectionFactory implements ClientConnectionFactory public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
@ -50,7 +51,7 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
public static final String SESSION_LISTENER_CONTEXT_KEY = "http2.client.sessionListener"; public static final String SESSION_LISTENER_CONTEXT_KEY = "http2.client.sessionListener";
public static final String SESSION_PROMISE_CONTEXT_KEY = "http2.client.sessionPromise"; public static final String SESSION_PROMISE_CONTEXT_KEY = "http2.client.sessionPromise";
private int initialSessionRecvWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE; private final Connection.Listener connectionListener = new ConnectionListener();
@Override @Override
public Connection newConnection(EndPoint endPoint, Map<String, Object> context) throws IOException public Connection newConnection(EndPoint endPoint, Map<String, Object> context) throws IOException
@ -67,7 +68,9 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
FlowControlStrategy flowControl = newFlowControlStrategy(); FlowControlStrategy flowControl = newFlowControlStrategy();
HTTP2ClientSession session = new HTTP2ClientSession(scheduler, endPoint, generator, listener, flowControl); HTTP2ClientSession session = new HTTP2ClientSession(scheduler, endPoint, generator, listener, flowControl);
Parser parser = new Parser(byteBufferPool, session, 4096, 8192); Parser parser = new Parser(byteBufferPool, session, 4096, 8192);
return new HTTP2ClientConnection(client, byteBufferPool, executor, endPoint, parser, session, 8192, promise, listener); HTTP2ClientConnection connection = new HTTP2ClientConnection(client, byteBufferPool, executor, endPoint, parser, session, client.getInputBufferSize(), promise, listener);
connection.addListener(connectionListener);
return connection;
} }
protected FlowControlStrategy newFlowControlStrategy() protected FlowControlStrategy newFlowControlStrategy()
@ -75,16 +78,6 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
return new BufferingFlowControlStrategy(0.5F); return new BufferingFlowControlStrategy(0.5F);
} }
public int getInitialSessionRecvWindow()
{
return initialSessionRecvWindow;
}
public void setInitialSessionRecvWindow(int initialSessionRecvWindow)
{
this.initialSessionRecvWindow = initialSessionRecvWindow;
}
private class HTTP2ClientConnection extends HTTP2Connection implements Callback private class HTTP2ClientConnection extends HTTP2Connection implements Callback
{ {
private final HTTP2Client client; private final HTTP2Client client;
@ -108,8 +101,10 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
PrefaceFrame prefaceFrame = new PrefaceFrame(); PrefaceFrame prefaceFrame = new PrefaceFrame();
SettingsFrame settingsFrame = new SettingsFrame(settings, false); SettingsFrame settingsFrame = new SettingsFrame(settings, false);
ISession session = getSession(); ISession session = getSession();
int windowDelta = getInitialSessionRecvWindow() - FlowControlStrategy.DEFAULT_WINDOW_SIZE;
int windowDelta = client.getInitialSessionRecvWindow() - FlowControlStrategy.DEFAULT_WINDOW_SIZE;
if (windowDelta > 0) if (windowDelta > 0)
{ {
session.updateRecvWindow(windowDelta); session.updateRecvWindow(windowDelta);
@ -138,4 +133,21 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory
promise.failed(x); promise.failed(x);
} }
} }
private class ConnectionListener implements Connection.Listener
{
@Override
public void onOpened(Connection connection)
{
HTTP2ClientConnection http2Connection = (HTTP2ClientConnection)connection;
http2Connection.client.addManaged((LifeCycle)http2Connection.getSession());
}
@Override
public void onClosed(Connection connection)
{
HTTP2ClientConnection http2Connection = (HTTP2ClientConnection)connection;
http2Connection.client.removeBean(http2Connection.getSession());
}
}
} }

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.http2.client;
import org.eclipse.jetty.http2.FlowControlStrategy; import org.eclipse.jetty.http2.FlowControlStrategy;
import org.eclipse.jetty.http2.HTTP2Session; import org.eclipse.jetty.http2.HTTP2Session;
import org.eclipse.jetty.http2.IStream; import org.eclipse.jetty.http2.IStream;
import org.eclipse.jetty.http2.api.Session;
import org.eclipse.jetty.http2.api.Stream; import org.eclipse.jetty.http2.api.Stream;
import org.eclipse.jetty.http2.frames.HeadersFrame; import org.eclipse.jetty.http2.frames.HeadersFrame;
import org.eclipse.jetty.http2.frames.PushPromiseFrame; import org.eclipse.jetty.http2.frames.PushPromiseFrame;
@ -35,7 +36,7 @@ public class HTTP2ClientSession extends HTTP2Session
{ {
private static final Logger LOG = Log.getLogger(HTTP2ClientSession.class); private static final Logger LOG = Log.getLogger(HTTP2ClientSession.class);
public HTTP2ClientSession(Scheduler scheduler, EndPoint endPoint, Generator generator, Listener listener, FlowControlStrategy flowControl) public HTTP2ClientSession(Scheduler scheduler, EndPoint endPoint, Generator generator, Session.Listener listener, FlowControlStrategy flowControl)
{ {
super(scheduler, endPoint, generator, listener, flowControl, 1); super(scheduler, endPoint, generator, listener, flowControl, 1);
} }

View File

@ -16,6 +16,12 @@
<artifactId>http2-hpack</artifactId> <artifactId>http2-hpack</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jmx</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency> <dependency>
<groupId>org.eclipse.jetty.toolchain</groupId> <groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId> <artifactId>jetty-test-helper</artifactId>
@ -23,30 +29,30 @@
</dependency> </dependency>
</dependencies> </dependencies>
<properties> <properties>
<bundle-symbolic-name>${project.groupId}.common</bundle-symbolic-name> <bundle-symbolic-name>${project.groupId}.common</bundle-symbolic-name>
</properties> </properties>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.felix</groupId> <groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId> <artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions> <extensions>true</extensions>
<executions> <executions>
<execution> <execution>
<goals> <goals>
<goal>manifest</goal> <goal>manifest</goal>
</goals> </goals>
<configuration> <configuration>
<instructions> <instructions>
<Export-Package>org.eclipse.jetty.http2.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}";</Export-Package> <Export-Package>org.eclipse.jetty.http2.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}";</Export-Package>
</instructions> </instructions>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

View File

@ -20,9 +20,12 @@ package org.eclipse.jetty.http2;
import org.eclipse.jetty.http2.api.Stream; import org.eclipse.jetty.http2.api.Stream;
import org.eclipse.jetty.http2.frames.WindowUpdateFrame; import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
@ManagedObject
public abstract class AbstractFlowControlStrategy implements FlowControlStrategy public abstract class AbstractFlowControlStrategy implements FlowControlStrategy
{ {
protected static final Logger LOG = Log.getLogger(FlowControlStrategy.class); protected static final Logger LOG = Log.getLogger(FlowControlStrategy.class);
@ -36,12 +39,14 @@ public abstract class AbstractFlowControlStrategy implements FlowControlStrategy
this.initialStreamRecvWindow = DEFAULT_WINDOW_SIZE; this.initialStreamRecvWindow = DEFAULT_WINDOW_SIZE;
} }
protected int getInitialStreamSendWindow() @ManagedAttribute(value = "The initial size of stream's flow control send window", readonly = true)
public int getInitialStreamSendWindow()
{ {
return initialStreamSendWindow; return initialStreamSendWindow;
} }
protected int getInitialStreamRecvWindow() @ManagedAttribute(value = "The initial size of stream's flow control receive window", readonly = true)
public int getInitialStreamRecvWindow()
{ {
return initialStreamRecvWindow; return initialStreamRecvWindow;
} }
@ -102,6 +107,8 @@ public abstract class AbstractFlowControlStrategy implements FlowControlStrategy
int oldSize = stream.updateSendWindow(delta); int oldSize = stream.updateSendWindow(delta);
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Updated stream send window {} -> {} for {}", oldSize, oldSize + delta, stream); LOG.debug("Updated stream send window {} -> {} for {}", oldSize, oldSize + delta, stream);
if (oldSize <= 0)
onStreamUnstalled(stream);
} }
} }
else else
@ -109,6 +116,8 @@ public abstract class AbstractFlowControlStrategy implements FlowControlStrategy
int oldSize = session.updateSendWindow(delta); int oldSize = session.updateSendWindow(delta);
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Updated session send window {} -> {} for {}", oldSize, oldSize + delta, session); LOG.debug("Updated session send window {} -> {} for {}", oldSize, oldSize + delta, session);
if (oldSize <= 0)
onSessionUnstalled(session);
} }
} }
@ -166,4 +175,16 @@ public abstract class AbstractFlowControlStrategy implements FlowControlStrategy
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("Stream stalled {}", stream); LOG.debug("Stream stalled {}", stream);
} }
protected void onSessionUnstalled(ISession session)
{
if (LOG.isDebugEnabled())
LOG.debug("Session unstalled {}", session);
}
protected void onStreamUnstalled(IStream stream)
{
if (LOG.isDebugEnabled())
LOG.debug("Stream unstalled {}", stream);
}
} }

View File

@ -26,6 +26,8 @@ import org.eclipse.jetty.http2.frames.Frame;
import org.eclipse.jetty.http2.frames.WindowUpdateFrame; import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
import org.eclipse.jetty.util.Atomics; import org.eclipse.jetty.util.Atomics;
import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
/** /**
* <p>A flow control strategy that accumulates updates and emits window control * <p>A flow control strategy that accumulates updates and emits window control
@ -49,6 +51,7 @@ import org.eclipse.jetty.util.Callback;
* <p>The application consumes the remaining 15, so now SB=15, and no window * <p>The application consumes the remaining 15, so now SB=15, and no window
* control frame is emitted.</p> * control frame is emitted.</p>
*/ */
@ManagedObject
public class BufferingFlowControlStrategy extends AbstractFlowControlStrategy public class BufferingFlowControlStrategy extends AbstractFlowControlStrategy
{ {
private final AtomicInteger maxSessionRecvWindow = new AtomicInteger(DEFAULT_WINDOW_SIZE); private final AtomicInteger maxSessionRecvWindow = new AtomicInteger(DEFAULT_WINDOW_SIZE);
@ -67,6 +70,12 @@ public class BufferingFlowControlStrategy extends AbstractFlowControlStrategy
this.bufferRatio = bufferRatio; this.bufferRatio = bufferRatio;
} }
@ManagedAttribute("The ratio between the receive buffer and the consume buffer")
public float getBufferRatio()
{
return bufferRatio;
}
@Override @Override
public void onStreamCreated(IStream stream) public void onStreamCreated(IStream stream)
{ {

View File

@ -54,11 +54,15 @@ import org.eclipse.jetty.util.Atomics;
import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.CountingCallback; import org.eclipse.jetty.util.CountingCallback;
import org.eclipse.jetty.util.Promise; import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.Scheduler;
public abstract class HTTP2Session implements ISession, Parser.Listener @ManagedObject
public abstract class HTTP2Session extends ContainerLifeCycle implements ISession, Parser.Listener
{ {
private static final Logger LOG = Log.getLogger(HTTP2Session.class); private static final Logger LOG = Log.getLogger(HTTP2Session.class);
@ -73,7 +77,7 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
private final Scheduler scheduler; private final Scheduler scheduler;
private final EndPoint endPoint; private final EndPoint endPoint;
private final Generator generator; private final Generator generator;
private final Listener listener; private final Session.Listener listener;
private final FlowControlStrategy flowControl; private final FlowControlStrategy flowControl;
private final HTTP2Flusher flusher; private final HTTP2Flusher flusher;
private int maxLocalStreams; private int maxLocalStreams;
@ -81,7 +85,7 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
private long streamIdleTimeout; private long streamIdleTimeout;
private boolean pushEnabled; private boolean pushEnabled;
public HTTP2Session(Scheduler scheduler, EndPoint endPoint, Generator generator, Listener listener, FlowControlStrategy flowControl, int initialStreamId) public HTTP2Session(Scheduler scheduler, EndPoint endPoint, Generator generator, Session.Listener listener, FlowControlStrategy flowControl, int initialStreamId)
{ {
this.scheduler = scheduler; this.scheduler = scheduler;
this.endPoint = endPoint; this.endPoint = endPoint;
@ -98,6 +102,14 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
this.pushEnabled = true; // SPEC: by default, push is enabled. this.pushEnabled = true; // SPEC: by default, push is enabled.
} }
@Override
protected void doStart() throws Exception
{
addBean(flowControl);
super.doStart();
}
@ManagedAttribute(value = "The flow control strategy", readonly = true)
public FlowControlStrategy getFlowControlStrategy() public FlowControlStrategy getFlowControlStrategy()
{ {
return flowControl; return flowControl;
@ -123,6 +135,7 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
this.maxRemoteStreams = maxRemoteStreams; this.maxRemoteStreams = maxRemoteStreams;
} }
@ManagedAttribute("The stream's idle timeout")
public long getStreamIdleTimeout() public long getStreamIdleTimeout()
{ {
return streamIdleTimeout; return streamIdleTimeout;
@ -709,17 +722,25 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
return result; return result;
} }
@ManagedAttribute("The number of active streams")
public int getStreamCount()
{
return streams.size();
}
@Override @Override
public IStream getStream(int streamId) public IStream getStream(int streamId)
{ {
return streams.get(streamId); return streams.get(streamId);
} }
@ManagedAttribute(value = "The flow control send window", readonly = true)
public int getSendWindow() public int getSendWindow()
{ {
return sendWindow.get(); return sendWindow.get();
} }
@ManagedAttribute(value = "The flow control receive window", readonly = true)
public int getRecvWindow() public int getRecvWindow()
{ {
return recvWindow.get(); return recvWindow.get();
@ -753,6 +774,7 @@ public abstract class HTTP2Session implements ISession, Parser.Listener
} }
@Override @Override
@ManagedAttribute(value = "Whether HTTP/2 push is enabled", readonly = true)
public boolean isPushEnabled() public boolean isPushEnabled()
{ {
return pushEnabled; return pushEnabled;

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.http2.client.http;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.eclipse.jetty.alpn.client.ALPNClientConnectionFactory; import org.eclipse.jetty.alpn.client.ALPNClientConnectionFactory;
@ -71,6 +72,7 @@ public class HttpClientTransportOverHTTP2 extends ContainerLifeCycle implements
client.setByteBufferPool(httpClient.getByteBufferPool()); client.setByteBufferPool(httpClient.getByteBufferPool());
client.setConnectTimeout(httpClient.getConnectTimeout()); client.setConnectTimeout(httpClient.getConnectTimeout());
client.setIdleTimeout(httpClient.getIdleTimeout()); client.setIdleTimeout(httpClient.getIdleTimeout());
client.setInputBufferSize(httpClient.getResponseBufferSize());
} }
addBean(client); addBean(client);
super.doStart(); super.doStart();
@ -160,6 +162,14 @@ public class HttpClientTransportOverHTTP2 extends ContainerLifeCycle implements
promise.failed(failure); promise.failed(failure);
} }
@Override
public Map<Integer, Integer> onPreface(Session session)
{
Map<Integer, Integer> settings = new HashMap<>();
settings.put(SettingsFrame.INITIAL_WINDOW_SIZE, client.getInitialStreamRecvWindow());
return settings;
}
@Override @Override
public void onSettings(Session session, SettingsFrame frame) public void onSettings(Session session, SettingsFrame frame)
{ {

View File

@ -31,15 +31,21 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.AbstractConnectionFactory; import org.eclipse.jetty.server.AbstractConnectionFactory;
import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.Name; import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.LifeCycle;
@ManagedObject
public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConnectionFactory public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConnectionFactory
{ {
private final Connection.Listener connectionListener = new ConnectionListener();
private final HttpConfiguration httpConfiguration;
private int maxDynamicTableSize = 4096; private int maxDynamicTableSize = 4096;
private int initialStreamSendWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE; private int initialStreamSendWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE;
private int maxConcurrentStreams = -1; private int maxConcurrentStreams = -1;
private int maxHeaderBlockFragment = 0; private int maxHeaderBlockFragment = 0;
private final HttpConfiguration httpConfiguration;
public AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration) public AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration)
{ {
@ -50,8 +56,10 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
{ {
super(protocols); super(protocols);
this.httpConfiguration = Objects.requireNonNull(httpConfiguration); this.httpConfiguration = Objects.requireNonNull(httpConfiguration);
addBean(httpConfiguration);
} }
@ManagedAttribute("The HPACK dynamic table maximum size")
public int getMaxDynamicTableSize() public int getMaxDynamicTableSize()
{ {
return maxDynamicTableSize; return maxDynamicTableSize;
@ -62,6 +70,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
this.maxDynamicTableSize = maxDynamicTableSize; this.maxDynamicTableSize = maxDynamicTableSize;
} }
@ManagedAttribute("The initial size of stream's flow control send window")
public int getInitialStreamSendWindow() public int getInitialStreamSendWindow()
{ {
return initialStreamSendWindow; return initialStreamSendWindow;
@ -72,6 +81,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
this.initialStreamSendWindow = initialStreamSendWindow; this.initialStreamSendWindow = initialStreamSendWindow;
} }
@ManagedAttribute("The max number of concurrent streams per session")
public int getMaxConcurrentStreams() public int getMaxConcurrentStreams()
{ {
return maxConcurrentStreams; return maxConcurrentStreams;
@ -116,7 +126,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
ServerParser parser = newServerParser(connector, session); ServerParser parser = newServerParser(connector, session);
HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(), HTTP2Connection connection = new HTTP2ServerConnection(connector.getByteBufferPool(), connector.getExecutor(),
endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener); endPoint, httpConfiguration, parser, session, getInputBufferSize(), listener);
connection.addListener(connectionListener);
return configure(connection, connector, endPoint); return configure(connection, connector, endPoint);
} }
@ -131,4 +141,19 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
{ {
return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize()); return new ServerParser(connector.getByteBufferPool(), listener, getMaxDynamicTableSize(), getHttpConfiguration().getRequestHeaderSize());
} }
private static class ConnectionListener extends ContainerLifeCycle implements Connection.Listener
{
@Override
public void onOpened(Connection connection)
{
addManaged((LifeCycle)((HTTP2Connection)connection).getSession());
}
@Override
public void onClosed(Connection connection)
{
removeBean(((HTTP2Connection)connection).getSession());
}
}
} }

View File

@ -26,22 +26,25 @@ import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.ArrayUtil; import org.eclipse.jetty.util.ArrayUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle; import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
/* ------------------------------------------------------------ */
/** /**
* Abstract ConnectionFactory * <p>Provides the common handling for {@link ConnectionFactory} implementations including:</p>
* <p>Provides the common handling for {@link ConnectionFactory} implementations including:<ul> * <ul>
* <li>Protocol identification * <li>Protocol identification</li>
* <li>Configuration of new Connections:<ul> * <li>Configuration of new Connections:
* <li>Setting inputbuffer size * <ul>
* <li>Calling {@link Connection#addListener(Connection.Listener)} for all * <li>Setting inputbuffer size</li>
* Connection.Listener instances found as beans on the {@link Connector} and this {@link ConnectionFactory} * <li>Calling {@link Connection#addListener(Connection.Listener)} for all
* </ul> * Connection.Listener instances found as beans on the {@link Connector}
* and this {@link ConnectionFactory}</li>
* </ul>
* </ul> * </ul>
*/ */
@ManagedObject
public abstract class AbstractConnectionFactory extends ContainerLifeCycle implements ConnectionFactory public abstract class AbstractConnectionFactory extends ContainerLifeCycle implements ConnectionFactory
{ {
private final String _protocol; private final String _protocol;
@ -53,7 +56,7 @@ public abstract class AbstractConnectionFactory extends ContainerLifeCycle imple
_protocol=protocol; _protocol=protocol;
_protocols=Collections.unmodifiableList(Arrays.asList(new String[]{protocol})); _protocols=Collections.unmodifiableList(Arrays.asList(new String[]{protocol}));
} }
protected AbstractConnectionFactory(String... protocols) protected AbstractConnectionFactory(String... protocols)
{ {
_protocol=protocols[0]; _protocol=protocols[0];
@ -61,6 +64,7 @@ public abstract class AbstractConnectionFactory extends ContainerLifeCycle imple
} }
@Override @Override
@ManagedAttribute(value = "The protocol name", readonly = true)
public String getProtocol() public String getProtocol()
{ {
return _protocol; return _protocol;
@ -72,6 +76,7 @@ public abstract class AbstractConnectionFactory extends ContainerLifeCycle imple
return _protocols; return _protocols;
} }
@ManagedAttribute("The buffer size used to read from the network")
public int getInputBufferSize() public int getInputBufferSize()
{ {
return _inputbufferSize; return _inputbufferSize;
@ -96,7 +101,7 @@ public abstract class AbstractConnectionFactory extends ContainerLifeCycle imple
// Add Connection.Listeners from this factory // Add Connection.Listeners from this factory
for (Connection.Listener listener : getBeans(Connection.Listener.class)) for (Connection.Listener listener : getBeans(Connection.Listener.class))
connection.addListener(listener); connection.addListener(listener);
return connection; return connection;
} }