From a0562d0acf174a52f05aa8413bf1b365e08ea70b Mon Sep 17 00:00:00 2001 From: Will Sargent Date: Mon, 7 Apr 2014 18:40:00 -0700 Subject: [PATCH 1/2] Add host and port to SSLEngineFactory, change the providers to accept host and port --- .../AsyncHttpClientConfig.java | 11 ++++++++ .../org/asynchttpclient/SSLEngineFactory.java | 10 ++++++++ .../org/asynchttpclient/util/SslUtils.java | 4 +-- .../netty/NettyAsyncHttpProvider.java | 5 +++- .../providers/netty/channel/Channels.java | 25 +++++++++++-------- .../providers/netty/handler/HttpProtocol.java | 3 ++- 6 files changed, 43 insertions(+), 15 deletions(-) diff --git a/api/src/main/java/org/asynchttpclient/AsyncHttpClientConfig.java b/api/src/main/java/org/asynchttpclient/AsyncHttpClientConfig.java index c352c7f43c..4094f44fd3 100644 --- a/api/src/main/java/org/asynchttpclient/AsyncHttpClientConfig.java +++ b/api/src/main/java/org/asynchttpclient/AsyncHttpClientConfig.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.io.InputStream; +import java.security.GeneralSecurityException; import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -351,6 +352,16 @@ public SSLEngine newSSLEngine() { return null; } } + + public SSLEngine newSSLEngine(String peerHost, int peerPort) throws GeneralSecurityException { + if (sslContext != null) { + SSLEngine sslEngine = sslContext.createSSLEngine(peerHost, peerPort); + sslEngine.setUseClientMode(true); + return sslEngine; + } else { + return null; + } + } }; } return sslEngineFactory; diff --git a/api/src/main/java/org/asynchttpclient/SSLEngineFactory.java b/api/src/main/java/org/asynchttpclient/SSLEngineFactory.java index 0289a0e109..913dfb74f7 100644 --- a/api/src/main/java/org/asynchttpclient/SSLEngineFactory.java +++ b/api/src/main/java/org/asynchttpclient/SSLEngineFactory.java @@ -30,4 +30,14 @@ public interface SSLEngineFactory { * @throws GeneralSecurityException if the SSLEngine cannot be created */ SSLEngine newSSLEngine() throws GeneralSecurityException; + + /** + * Creates new {@link SSLEngine}. + * + * @param peerHost the hostname of the peer the engine is connecting to. + * @param peerPort the port of the peer the engine is connecting to. + * @return new engine + * @throws GeneralSecurityException if the SSLEngine cannot be created + */ + SSLEngine newSSLEngine(String peerHost, int peerPort) throws GeneralSecurityException; } diff --git a/api/src/main/java/org/asynchttpclient/util/SslUtils.java b/api/src/main/java/org/asynchttpclient/util/SslUtils.java index 29c7b70011..72a64faef6 100644 --- a/api/src/main/java/org/asynchttpclient/util/SslUtils.java +++ b/api/src/main/java/org/asynchttpclient/util/SslUtils.java @@ -38,12 +38,12 @@ public class SslUtils { private static SSLContext context = null; - public static SSLEngine getSSLEngine() throws GeneralSecurityException, IOException { + public static SSLEngine getSSLEngine(String peerHost, int peerPort) throws GeneralSecurityException, IOException { SSLEngine engine = null; SSLContext context = getSSLContext(); if (context != null) { - engine = context.createSSLEngine(); + engine = context.createSSLEngine(peerHost, peerPort); engine.setUseClientMode(true); } diff --git a/providers/netty/src/main/java/org/asynchttpclient/providers/netty/NettyAsyncHttpProvider.java b/providers/netty/src/main/java/org/asynchttpclient/providers/netty/NettyAsyncHttpProvider.java index 01d71e1baf..91da5129aa 100644 --- a/providers/netty/src/main/java/org/asynchttpclient/providers/netty/NettyAsyncHttpProvider.java +++ b/providers/netty/src/main/java/org/asynchttpclient/providers/netty/NettyAsyncHttpProvider.java @@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory; import java.io.IOException; +import java.net.URI; import java.util.concurrent.atomic.AtomicBoolean; public class NettyAsyncHttpProvider implements AsyncHttpProvider { @@ -47,7 +48,6 @@ public NettyAsyncHttpProvider(AsyncHttpClientConfig config) { channels = new Channels(config, nettyConfig); requestSender = new NettyRequestSender(closed, config, nettyConfig, channels); - channels.configureProcessor(requestSender, closed); } @Override @@ -72,6 +72,9 @@ public void close() { @Override public ListenableFuture execute(Request request, final AsyncHandler asyncHandler) throws IOException { + final URI uri = request.getURI(); + channels.configureProcessor(requestSender, closed, uri.getHost(), uri.getPort()); + return requestSender.sendRequest(request, asyncHandler, null, false); } } diff --git a/providers/netty/src/main/java/org/asynchttpclient/providers/netty/channel/Channels.java b/providers/netty/src/main/java/org/asynchttpclient/providers/netty/channel/Channels.java index 1182ef4d5d..b3c3cfbb37 100644 --- a/providers/netty/src/main/java/org/asynchttpclient/providers/netty/channel/Channels.java +++ b/providers/netty/src/main/java/org/asynchttpclient/providers/netty/channel/Channels.java @@ -195,15 +195,18 @@ public Channels(final AsyncHttpClientConfig config, NettyAsyncHttpProviderConfig secureWebSocketBootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, timeOut); } - private SSLEngine createSSLEngine() throws IOException, GeneralSecurityException { - SSLEngine sslEngine = config.getSSLEngineFactory().newSSLEngine(); + private SSLEngine createSSLEngine(String peerHost, int peerPort) throws IOException, GeneralSecurityException { + SSLEngine sslEngine = config.getSSLEngineFactory().newSSLEngine(peerHost, peerPort); if (sslEngine == null) { - sslEngine = SslUtils.getSSLEngine(); + sslEngine = SslUtils.getSSLEngine(peerHost, peerPort); } return sslEngine; } - public void configureProcessor(NettyRequestSender requestSender, AtomicBoolean closed) { + public void configureProcessor(final NettyRequestSender requestSender,// + final AtomicBoolean closed,// + final String peerHost,// + final int peerPort) { final Processor httpProcessor = newHttpProcessor(config, nettyProviderConfig, requestSender, this, closed); wsProcessor = newWsProcessor(config, nettyProviderConfig, requestSender, this, closed); @@ -243,7 +246,7 @@ protected void initChannel(Channel ch) throws Exception { @Override protected void initChannel(Channel ch) throws Exception { - SSLEngine sslEngine = createSSLEngine(); + SSLEngine sslEngine = createSSLEngine(peerHost, peerPort); SslHandler sslHandler = new SslHandler(sslEngine); if (handshakeTimeoutInMillis > 0) sslHandler.setHandshakeTimeoutMillis(handshakeTimeoutInMillis); @@ -269,7 +272,7 @@ protected void initChannel(Channel ch) throws Exception { @Override protected void initChannel(Channel ch) throws Exception { ch.pipeline()// - .addLast(SSL_HANDLER, new SslHandler(createSSLEngine()))// + .addLast(SSL_HANDLER, new SslHandler(createSSLEngine(peerHost, peerPort)))// .addLast(HTTP_HANDLER, newHttpClientCodec())// .addLast(WS_PROCESSOR, wsProcessor); @@ -307,7 +310,7 @@ public void close() { * Always make sure the channel who got cached support the proper protocol. It could only occurs when a HttpMethod. * CONNECT is used against a proxy that requires upgrading from http to https. */ - public void verifyChannelPipeline(ChannelPipeline pipeline, String scheme) throws IOException, GeneralSecurityException { + public void verifyChannelPipeline(ChannelPipeline pipeline, String scheme, String peerHost, int peerPort) throws IOException, GeneralSecurityException { boolean isSecure = isSecure(scheme); if (pipeline.get(SSL_HANDLER) != null) { @@ -315,7 +318,7 @@ public void verifyChannelPipeline(ChannelPipeline pipeline, String scheme) throw pipeline.remove(SSL_HANDLER); } else if (isSecure) - pipeline.addFirst(SSL_HANDLER, new SslHandler(createSSLEngine())); + pipeline.addFirst(SSL_HANDLER, new SslHandler(createSSLEngine(peerHost, peerPort))); } protected HttpClientCodec newHttpClientCodec() { @@ -331,7 +334,7 @@ protected HttpClientCodec newHttpClientCodec() { } } - public void upgradeProtocol(ChannelPipeline p, String scheme) throws IOException, GeneralSecurityException { + public void upgradeProtocol(ChannelPipeline p, String scheme, String peerHost, int peerPort) throws IOException, GeneralSecurityException { if (p.get(HTTP_HANDLER) != null) { p.remove(HTTP_HANDLER); } @@ -339,7 +342,7 @@ public void upgradeProtocol(ChannelPipeline p, String scheme) throws IOException if (isSecure(scheme)) { if (p.get(SSL_HANDLER) == null) { p.addFirst(HTTP_HANDLER, newHttpClientCodec()); - p.addFirst(SSL_HANDLER, new SslHandler(createSSLEngine())); + p.addFirst(SSL_HANDLER, new SslHandler(createSSLEngine(peerHost, peerPort))); } else { p.addAfter(SSL_HANDLER, HTTP_HANDLER, newHttpClientCodec()); } @@ -365,7 +368,7 @@ public Channel pollAndVerifyCachedChannel(URI uri, ProxyServer proxy, Connection LOGGER.debug("Using cached Channel {}\n for uri {}\n", channel, uri); try { - verifyChannelPipeline(channel.pipeline(), uri.getScheme()); + verifyChannelPipeline(channel.pipeline(), uri.getScheme(), uri.getHost(), uri.getPort()); } catch (Exception ex) { LOGGER.debug(ex.getMessage(), ex); } diff --git a/providers/netty/src/main/java/org/asynchttpclient/providers/netty/handler/HttpProtocol.java b/providers/netty/src/main/java/org/asynchttpclient/providers/netty/handler/HttpProtocol.java index 61bbe02c0a..e59d4b9e5c 100644 --- a/providers/netty/src/main/java/org/asynchttpclient/providers/netty/handler/HttpProtocol.java +++ b/providers/netty/src/main/java/org/asynchttpclient/providers/netty/handler/HttpProtocol.java @@ -320,7 +320,8 @@ private boolean handleConnectOKAndExit(int statusCode, Realm realm, final Reques try { LOGGER.debug("Connecting to proxy {} for scheme {}", proxyServer, request.getUrl()); - channels.upgradeProtocol(channel.pipeline(), request.getURI().getScheme()); + URI uri = request.getURI(); + channels.upgradeProtocol(channel.pipeline(), uri.getScheme(), uri.getHost(), uri.getPort()); } catch (Throwable ex) { channels.abort(future, ex); } From 17f795678bae61c664f62b49729385cd159533bd Mon Sep 17 00:00:00 2001 From: Will Sargent Date: Tue, 8 Apr 2014 12:03:47 -0700 Subject: [PATCH 2/2] Use AsyncHttpProviderUtils.getHost/getPort (avoids -1 for default port problem) --- .../providers/netty/NettyAsyncHttpProvider.java | 5 ++++- .../asynchttpclient/providers/netty/channel/Channels.java | 5 ++++- .../providers/netty/handler/HttpProtocol.java | 6 ++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/providers/netty/src/main/java/org/asynchttpclient/providers/netty/NettyAsyncHttpProvider.java b/providers/netty/src/main/java/org/asynchttpclient/providers/netty/NettyAsyncHttpProvider.java index 91da5129aa..df89f05ec6 100644 --- a/providers/netty/src/main/java/org/asynchttpclient/providers/netty/NettyAsyncHttpProvider.java +++ b/providers/netty/src/main/java/org/asynchttpclient/providers/netty/NettyAsyncHttpProvider.java @@ -22,6 +22,7 @@ import org.asynchttpclient.Request; import org.asynchttpclient.providers.netty.channel.Channels; import org.asynchttpclient.providers.netty.request.NettyRequestSender; +import org.asynchttpclient.util.AsyncHttpProviderUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -73,7 +74,9 @@ public void close() { @Override public ListenableFuture execute(Request request, final AsyncHandler asyncHandler) throws IOException { final URI uri = request.getURI(); - channels.configureProcessor(requestSender, closed, uri.getHost(), uri.getPort()); + final String host = AsyncHttpProviderUtils.getHost(uri); + final int port = AsyncHttpProviderUtils.getPort(uri); + channels.configureProcessor(requestSender, closed, host, port); return requestSender.sendRequest(request, asyncHandler, null, false); } diff --git a/providers/netty/src/main/java/org/asynchttpclient/providers/netty/channel/Channels.java b/providers/netty/src/main/java/org/asynchttpclient/providers/netty/channel/Channels.java index b3c3cfbb37..ba666349cf 100644 --- a/providers/netty/src/main/java/org/asynchttpclient/providers/netty/channel/Channels.java +++ b/providers/netty/src/main/java/org/asynchttpclient/providers/netty/channel/Channels.java @@ -32,6 +32,7 @@ import org.asynchttpclient.providers.netty.handler.Processor; import org.asynchttpclient.providers.netty.request.NettyRequestSender; import org.asynchttpclient.providers.netty.util.CleanupChannelGroup; +import org.asynchttpclient.util.AsyncHttpProviderUtils; import org.asynchttpclient.util.SslUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -368,7 +369,9 @@ public Channel pollAndVerifyCachedChannel(URI uri, ProxyServer proxy, Connection LOGGER.debug("Using cached Channel {}\n for uri {}\n", channel, uri); try { - verifyChannelPipeline(channel.pipeline(), uri.getScheme(), uri.getHost(), uri.getPort()); + final String host = AsyncHttpProviderUtils.getHost(uri); + final int port = AsyncHttpProviderUtils.getPort(uri); + verifyChannelPipeline(channel.pipeline(), uri.getScheme(), host, port); } catch (Exception ex) { LOGGER.debug(ex.getMessage(), ex); } diff --git a/providers/netty/src/main/java/org/asynchttpclient/providers/netty/handler/HttpProtocol.java b/providers/netty/src/main/java/org/asynchttpclient/providers/netty/handler/HttpProtocol.java index e59d4b9e5c..2f529156e5 100644 --- a/providers/netty/src/main/java/org/asynchttpclient/providers/netty/handler/HttpProtocol.java +++ b/providers/netty/src/main/java/org/asynchttpclient/providers/netty/handler/HttpProtocol.java @@ -320,8 +320,10 @@ private boolean handleConnectOKAndExit(int statusCode, Realm realm, final Reques try { LOGGER.debug("Connecting to proxy {} for scheme {}", proxyServer, request.getUrl()); - URI uri = request.getURI(); - channels.upgradeProtocol(channel.pipeline(), uri.getScheme(), uri.getHost(), uri.getPort()); + final URI uri = request.getURI(); + final String host = AsyncHttpProviderUtils.getHost(uri); + final int port = AsyncHttpProviderUtils.getPort(uri); + channels.upgradeProtocol(channel.pipeline(), uri.getScheme(), host, port); } catch (Throwable ex) { channels.abort(future, ex); }