diff --git a/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2Client.java b/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2Client.java index 4c43e196cbf..ad5d8c9da09 100644 --- a/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2Client.java +++ b/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2Client.java @@ -30,6 +30,7 @@ import java.util.Map; import java.util.concurrent.Executor; import org.eclipse.jetty.alpn.client.ALPNClientConnectionFactory; +import org.eclipse.jetty.http2.BufferingFlowControlStrategy; import org.eclipse.jetty.http2.FlowControlStrategy; import org.eclipse.jetty.http2.api.Session; import org.eclipse.jetty.io.ByteBufferPool; @@ -125,6 +126,7 @@ public class HTTP2Client extends ContainerLifeCycle private List 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; + private FlowControlStrategy.Factory flowControlStrategyFactory = () -> new BufferingFlowControlStrategy(0.5F); @Override protected void doStart() throws Exception @@ -213,6 +215,16 @@ public class HTTP2Client extends ContainerLifeCycle this.connectionFactory = connectionFactory; } + public FlowControlStrategy.Factory getFlowControlStrategyFactory() + { + return flowControlStrategyFactory; + } + + public void setFlowControlStrategyFactory(FlowControlStrategy.Factory flowControlStrategyFactory) + { + this.flowControlStrategyFactory = flowControlStrategyFactory; + } + @ManagedAttribute("The number of selectors") public int getSelectors() { diff --git a/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2ClientConnectionFactory.java b/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2ClientConnectionFactory.java index b1e75b9bed2..b5d522114b0 100644 --- a/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2ClientConnectionFactory.java +++ b/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2ClientConnectionFactory.java @@ -23,7 +23,6 @@ import java.util.Collections; import java.util.Map; import java.util.concurrent.Executor; -import org.eclipse.jetty.http2.BufferingFlowControlStrategy; import org.eclipse.jetty.http2.FlowControlStrategy; import org.eclipse.jetty.http2.HTTP2Connection; import org.eclipse.jetty.http2.ISession; @@ -65,7 +64,7 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory Promise promise = (Promise)context.get(SESSION_PROMISE_CONTEXT_KEY); Generator generator = new Generator(byteBufferPool); - FlowControlStrategy flowControl = newFlowControlStrategy(); + FlowControlStrategy flowControl = client.getFlowControlStrategyFactory().newFlowControlStrategy(); HTTP2ClientSession session = new HTTP2ClientSession(scheduler, endPoint, generator, listener, flowControl); Parser parser = new Parser(byteBufferPool, session, 4096, 8192); HTTP2ClientConnection connection = new HTTP2ClientConnection(client, byteBufferPool, executor, endPoint, parser, session, client.getInputBufferSize(), promise, listener); @@ -73,11 +72,6 @@ public class HTTP2ClientConnectionFactory implements ClientConnectionFactory return connection; } - protected FlowControlStrategy newFlowControlStrategy() - { - return new BufferingFlowControlStrategy(0.5F); - } - private class HTTP2ClientConnection extends HTTP2Connection implements Callback { private final HTTP2Client client; diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java index 8af193c8c7f..82d2e26c686 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java @@ -27,7 +27,6 @@ import java.util.Queue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Supplier; import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpFields; @@ -67,19 +66,14 @@ public class FlowControlStalledTest protected HTTP2Client client; protected Server server; - protected void start(Supplier flowControlFactory, ServerSessionListener listener) throws Exception + protected void start(FlowControlStrategy.Factory flowControlFactory, ServerSessionListener listener) throws Exception { QueuedThreadPool serverExecutor = new QueuedThreadPool(); serverExecutor.setName("server"); server = new Server(serverExecutor); - connector = new ServerConnector(server, new RawHTTP2ServerConnectionFactory(new HttpConfiguration(), listener) - { - @Override - protected FlowControlStrategy newFlowControlStrategy() - { - return flowControlFactory.get(); - } - }); + RawHTTP2ServerConnectionFactory connectionFactory = new RawHTTP2ServerConnectionFactory(new HttpConfiguration(), listener); + connectionFactory.setFlowControlStrategyFactory(flowControlFactory); + connector = new ServerConnector(server, connectionFactory); server.addConnector(connector); server.start(); @@ -87,14 +81,7 @@ public class FlowControlStalledTest QueuedThreadPool clientExecutor = new QueuedThreadPool(); clientExecutor.setName("client"); client.setExecutor(clientExecutor); - client.setClientConnectionFactory(new HTTP2ClientConnectionFactory() - { - @Override - protected FlowControlStrategy newFlowControlStrategy() - { - return flowControlFactory.get(); - } - }); + client.setFlowControlStrategyFactory(flowControlFactory); client.start(); } diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java index e27ca4ab9f7..667fa68a11d 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java @@ -84,14 +84,9 @@ public abstract class FlowControlStrategyTest QueuedThreadPool serverExecutor = new QueuedThreadPool(); serverExecutor.setName("server"); server = new Server(serverExecutor); - connector = new ServerConnector(server, new RawHTTP2ServerConnectionFactory(new HttpConfiguration(), listener) - { - @Override - protected FlowControlStrategy newFlowControlStrategy() - { - return FlowControlStrategyTest.this.newFlowControlStrategy(); - } - }); + RawHTTP2ServerConnectionFactory connectionFactory = new RawHTTP2ServerConnectionFactory(new HttpConfiguration(), listener); + connectionFactory.setFlowControlStrategyFactory(FlowControlStrategyTest.this::newFlowControlStrategy); + connector = new ServerConnector(server, connectionFactory); server.addConnector(connector); server.start(); @@ -99,14 +94,7 @@ public abstract class FlowControlStrategyTest QueuedThreadPool clientExecutor = new QueuedThreadPool(); clientExecutor.setName("client"); client.setExecutor(clientExecutor); - client.setClientConnectionFactory(new HTTP2ClientConnectionFactory() - { - @Override - protected FlowControlStrategy newFlowControlStrategy() - { - return FlowControlStrategyTest.this.newFlowControlStrategy(); - } - }); + client.setFlowControlStrategyFactory(FlowControlStrategyTest.this::newFlowControlStrategy); client.start(); } diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/AbstractFlowControlStrategy.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/AbstractFlowControlStrategy.java index b2908107a70..41bba462c4a 100644 --- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/AbstractFlowControlStrategy.java +++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/AbstractFlowControlStrategy.java @@ -155,14 +155,14 @@ public abstract class AbstractFlowControlStrategy implements FlowControlStrategy int oldSessionWindow = session.updateSendWindow(-length); int newSessionWindow = oldSessionWindow - length; if (LOG.isDebugEnabled()) - LOG.debug("Updated session send window {} -> {} for {}", oldSessionWindow, newSessionWindow, session); + LOG.debug("Sending, session send window {} -> {} for {}", oldSessionWindow, newSessionWindow, session); if (newSessionWindow <= 0) onSessionStalled(session); int oldStreamWindow = stream.updateSendWindow(-length); int newStreamWindow = oldStreamWindow - length; if (LOG.isDebugEnabled()) - LOG.debug("Updated stream send window {} -> {} for {}", oldStreamWindow, newStreamWindow, stream); + LOG.debug("Sending, stream send window {} -> {} for {}", oldStreamWindow, newStreamWindow, stream); if (newStreamWindow <= 0) onStreamStalled(stream); } diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/FlowControlStrategy.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/FlowControlStrategy.java index d4e86b16f28..500ee3d1b9d 100644 --- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/FlowControlStrategy.java +++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/FlowControlStrategy.java @@ -41,4 +41,9 @@ public interface FlowControlStrategy public void onDataSending(IStream stream, int length); public void onDataSent(IStream stream, int length); + + public interface Factory + { + public FlowControlStrategy newFlowControlStrategy(); + } } diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java index 61f581c2016..95414ccfd72 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/AbstractHTTP2ServerConnectionFactory.java @@ -46,6 +46,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne private int initialStreamSendWindow = FlowControlStrategy.DEFAULT_WINDOW_SIZE; private int maxConcurrentStreams = -1; private int maxHeaderBlockFragment = 0; + private FlowControlStrategy.Factory flowControlStrategyFactory = () -> new BufferingFlowControlStrategy(0.5F); public AbstractHTTP2ServerConnectionFactory(@Name("config") HttpConfiguration httpConfiguration) { @@ -102,6 +103,16 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne this.maxHeaderBlockFragment = maxHeaderBlockFragment; } + public FlowControlStrategy.Factory getFlowControlStrategyFactory() + { + return flowControlStrategyFactory; + } + + public void setFlowControlStrategyFactory(FlowControlStrategy.Factory flowControlStrategyFactory) + { + this.flowControlStrategyFactory = flowControlStrategyFactory; + } + public HttpConfiguration getHttpConfiguration() { return httpConfiguration; @@ -113,7 +124,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne ServerSessionListener listener = newSessionListener(connector, endPoint); Generator generator = new Generator(connector.getByteBufferPool(), getMaxDynamicTableSize(), getMaxHeaderBlockFragment()); - FlowControlStrategy flowControl = newFlowControlStrategy(); + FlowControlStrategy flowControl = getFlowControlStrategyFactory().newFlowControlStrategy(); HTTP2ServerSession session = new HTTP2ServerSession(connector.getScheduler(), endPoint, generator, listener, flowControl); session.setMaxLocalStreams(getMaxConcurrentStreams()); session.setMaxRemoteStreams(getMaxConcurrentStreams()); @@ -130,11 +141,6 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne return configure(connection, connector, endPoint); } - protected FlowControlStrategy newFlowControlStrategy() - { - return new BufferingFlowControlStrategy(getInitialStreamSendWindow(), 0.5F); - } - protected abstract ServerSessionListener newSessionListener(Connector connector, EndPoint endPoint); protected ServerParser newServerParser(Connector connector, ServerParser.Listener listener) diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AbstractTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AbstractTest.java index 72b4ec45a86..0f3d21542aa 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AbstractTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AbstractTest.java @@ -105,7 +105,7 @@ public abstract class AbstractTest { QueuedThreadPool clientThreads = new QueuedThreadPool(); clientThreads.setName("client"); - client = new HttpClient(provideClientTransport(transport), sslContextFactory); + client = newHttpClient(provideClientTransport(transport), sslContextFactory); client.setExecutor(clientThreads); client.setSocketAddressResolver(new SocketAddressResolver.Sync()); client.start(); @@ -187,6 +187,11 @@ public abstract class AbstractTest } } + protected HttpClient newHttpClient(HttpClientTransport transport, SslContextFactory sslContextFactory) + { + return new HttpClient(transport, sslContextFactory); + } + protected HTTP2Client newHTTP2Client() { HTTP2Client http2Client = new HTTP2Client();