From b71cd70bf74df78084a22bd903673b6323c6e1a9 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Wed, 7 Mar 2018 11:52:28 +0100 Subject: [PATCH] Fixes #2297 - HTTP/2 client transport should honor HttpClient.connectBlocking. Introduced property connectBlocking in HTTP2Client so that it can be forwarded by HttpClient and then used for HTTP/2 connects. Also introduced HTTP2Client.bindAddress, again forwarded from HttpClient. Signed-off-by: Simone Bordet --- .../AbstractConnectorHttpClientTransport.java | 11 ++--- .../jetty/http2/client/HTTP2Client.java | 41 ++++++++++++++++++- .../http/HttpClientTransportOverHTTP2.java | 7 +++- 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectorHttpClientTransport.java b/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectorHttpClientTransport.java index 4644c08a03e..669ba41d757 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectorHttpClientTransport.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/AbstractConnectorHttpClientTransport.java @@ -88,20 +88,21 @@ public abstract class AbstractConnectorHttpClientTransport extends AbstractHttpC context.put(SslClientConnectionFactory.SSL_PEER_HOST_CONTEXT_KEY, destination.getHost()); context.put(SslClientConnectionFactory.SSL_PEER_PORT_CONTEXT_KEY, destination.getPort()); + boolean connected = true; if (client.isConnectBlocking()) { channel.socket().connect(address, (int)client.getConnectTimeout()); channel.configureBlocking(false); - selectorManager.accept(channel, context); } else { channel.configureBlocking(false); - if (channel.connect(address)) - selectorManager.accept(channel, context); - else - selectorManager.connect(channel, context); + connected = channel.connect(address); } + if (connected) + selectorManager.accept(channel, context); + else + selectorManager.connect(channel, context); } // Must catch all exceptions, since some like // UnresolvedAddressException are not IOExceptions. 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 1eb23d3da7b..83ff1c487e7 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 @@ -20,6 +20,7 @@ package org.eclipse.jetty.http2.client; import java.io.IOException; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.SocketChannel; @@ -122,6 +123,8 @@ public class HTTP2Client extends ContainerLifeCycle private int selectors = 1; private long idleTimeout = 30000; private long connectTimeout = 10000; + private boolean connectBlocking; + private SocketAddress bindAddress; private int inputBufferSize = 8192; private List protocols = Arrays.asList("h2", "h2-17", "h2-16", "h2-15", "h2-14"); private int initialSessionRecvWindow = 16 * 1024 * 1024; @@ -266,6 +269,27 @@ public class HTTP2Client extends ContainerLifeCycle selector.setConnectTimeout(connectTimeout); } + @ManagedAttribute("Whether the connect() operation is blocking") + public boolean isConnectBlocking() + { + return connectBlocking; + } + + public void setConnectBlocking(boolean connectBlocking) + { + this.connectBlocking = connectBlocking; + } + + public SocketAddress getBindAddress() + { + return bindAddress; + } + + public void setBindAddress(SocketAddress bindAddress) + { + this.bindAddress = bindAddress; + } + @ManagedAttribute("The size of the buffer used to read from the network") public int getInputBufferSize() { @@ -325,10 +349,23 @@ public class HTTP2Client extends ContainerLifeCycle try { SocketChannel channel = SocketChannel.open(); + SocketAddress bindAddress = getBindAddress(); + if (bindAddress != null) + channel.bind(bindAddress); configure(channel); - channel.configureBlocking(false); + boolean connected = true; + if (isConnectBlocking()) + { + channel.socket().connect(address, (int)getConnectTimeout()); + channel.configureBlocking(false); + } + else + { + channel.configureBlocking(false); + connected = channel.connect(address); + } context = contextFrom(sslContextFactory, address, listener, promise, context); - if (channel.connect(address)) + if (connected) selector.accept(channel, context); else selector.connect(channel, context); diff --git a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2.java b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2.java index 0bcb1ceb05e..f024d8974ef 100644 --- a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2.java +++ b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2.java @@ -124,14 +124,17 @@ public class HttpClientTransportOverHTTP2 extends AbstractHttpClientTransport @Override public void connect(InetSocketAddress address, Map context) { - client.setConnectTimeout(getHttpClient().getConnectTimeout()); + HttpClient httpClient = getHttpClient(); + client.setConnectTimeout(httpClient.getConnectTimeout()); + client.setConnectBlocking(httpClient.isConnectBlocking()); + client.setBindAddress(httpClient.getBindAddress()); SessionListenerPromise listenerPromise = new SessionListenerPromise(context); HttpDestinationOverHTTP2 destination = (HttpDestinationOverHTTP2)context.get(HTTP_DESTINATION_CONTEXT_KEY); SslContextFactory sslContextFactory = null; if (HttpScheme.HTTPS.is(destination.getScheme())) - sslContextFactory = getHttpClient().getSslContextFactory(); + sslContextFactory = httpClient.getSslContextFactory(); client.connect(sslContextFactory, address, listenerPromise, listenerPromise, context); }