diff --git a/httpclient/src/main/java/org/apache/http/conn/ConnectTimeoutException.java b/httpclient/src/main/java/org/apache/http/conn/ConnectTimeoutException.java index 8f68aafc0..fa69e2ee0 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ConnectTimeoutException.java +++ b/httpclient/src/main/java/org/apache/http/conn/ConnectTimeoutException.java @@ -28,7 +28,9 @@ package org.apache.http.conn; import java.io.InterruptedIOException; +import java.net.InetSocketAddress; +import org.apache.http.HttpHost; import org.apache.http.annotation.Immutable; /** @@ -59,4 +61,18 @@ public class ConnectTimeoutException extends InterruptedIOException { super(message); } + /** + * Creates a ConnectTimeoutException with the specified detail message. + * + * @param message The exception detail message + * + * @since 4.3 + */ + public ConnectTimeoutException(final HttpHost host, final InetSocketAddress remoteAddress) { + super("Connect to " + + (host != null ? host.toHostString() : " remote host") + + (remoteAddress != null ? " (" + remoteAddress.getAddress() + ")" : "") + + " timed out"); + } + } diff --git a/httpclient/src/main/java/org/apache/http/conn/HttpInetSocketAddress.java b/httpclient/src/main/java/org/apache/http/conn/HttpInetSocketAddress.java index c59d212ef..861f58dd4 100644 --- a/httpclient/src/main/java/org/apache/http/conn/HttpInetSocketAddress.java +++ b/httpclient/src/main/java/org/apache/http/conn/HttpInetSocketAddress.java @@ -35,8 +35,11 @@ import org.apache.http.HttpHost; * Extended {@link InetSocketAddress} implementation that also provides access to the original * {@link HttpHost} used to resolve the address. * - * @since 4.2 + * @since 4.2 no longer used. + * + * @deprecated (4.3) */ +@Deprecated public class HttpInetSocketAddress extends InetSocketAddress { private static final long serialVersionUID = -6650701828361907957L; diff --git a/httpclient/src/main/java/org/apache/http/conn/scheme/PlainSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/scheme/PlainSocketFactory.java index 7a9254ead..6a512efcb 100644 --- a/httpclient/src/main/java/org/apache/http/conn/scheme/PlainSocketFactory.java +++ b/httpclient/src/main/java/org/apache/http/conn/scheme/PlainSocketFactory.java @@ -43,18 +43,13 @@ import org.apache.http.params.HttpParams; /** * The default class for creating plain (unencrypted) sockets. - *

- * The following parameters can be used to customize the behavior of this - * class: - *

* * @since 4.0 + * + * @deprecated (4.3) use {@link org.apache.http.conn.socket.PlainSocketFactory} */ -@SuppressWarnings("deprecation") @Immutable +@Deprecated public class PlainSocketFactory implements SocketFactory, SchemeSocketFactory { private final HostNameResolver nameResolver; diff --git a/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeLayeredSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeLayeredSocketFactory.java index 7ede8cd53..2eb7272e2 100644 --- a/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeLayeredSocketFactory.java +++ b/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeLayeredSocketFactory.java @@ -37,7 +37,10 @@ import org.apache.http.params.HttpParams; * Extended {@link SchemeSocketFactory} interface for layered sockets such as SSL/TLS. * * @since 4.2 + * + * @deprecated (4.3) use {@link LayeredConnectionSocketFactory} */ +@Deprecated public interface SchemeLayeredSocketFactory extends SchemeSocketFactory { /** diff --git a/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeSocketFactory.java index 43fca33c2..d124bc8e1 100644 --- a/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeSocketFactory.java +++ b/httpclient/src/main/java/org/apache/http/conn/scheme/SchemeSocketFactory.java @@ -35,6 +35,7 @@ import java.net.UnknownHostException; import org.apache.http.HttpHost; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.HttpInetSocketAddress; +import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.params.HttpParams; /** @@ -42,7 +43,10 @@ import org.apache.http.params.HttpParams; * for establishing a socket connection. * * @since 4.1 + * + * @deprecated (4.3) use {@link ConnectionSocketFactory} */ +@Deprecated public interface SchemeSocketFactory { /** diff --git a/httpclient/src/main/java/org/apache/http/conn/socket/ConnectionSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/socket/ConnectionSocketFactory.java new file mode 100644 index 000000000..cb15d998b --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/conn/socket/ConnectionSocketFactory.java @@ -0,0 +1,87 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.conn.socket; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; + +import org.apache.http.HttpHost; +import org.apache.http.config.SocketConfig; +import org.apache.http.conn.ConnectTimeoutException; +import org.apache.http.protocol.HttpContext; + +/** + * A factory for creating and connecting sockets. + * + * @since 4.3 + */ +public interface ConnectionSocketFactory { + + /** + * Creates new, unconnected socket. The socket should subsequently be passed to + * {@link #connectSocket(Socket, SocketConfig, HttpHost, InetSocketAddress, InetSocketAddress, + * HttpContext))}. + * + * @return a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + */ + Socket createSocket(HttpContext context) throws IOException; + + /** + * Connects a socket to the target host with the given resolved remote address. + * + * @param connectTimeout connect timeout. + * @param sock the socket to connect, as obtained from {@link #createSocket(HttpContext)}. + * null indicates that a new socket should be created and connected. + * @param config Socket configuration. If null {@link SocketConfig#DEFAULT} + * will be used. + * @param host target host as specified by the caller (end user). + * @param remoteAddress the resolved remote address to connect to. + * @param localAddress the local address to bind the socket to, or null for any. + * @param context the actual HTTP context. + * + * @return the connected socket. The returned object may be different + * from the sock argument if this factory supports + * a layered protocol. + * + * @throws IOException if an I/O error occurs + * @throws ConnectTimeoutException if the socket cannot be connected + * within the time limit defined in the params + */ + Socket connectSocket( + int connectTimeout, + Socket sock, + SocketConfig config, + HttpHost host, + InetSocketAddress remoteAddress, + InetSocketAddress localAddress, + HttpContext context) throws IOException, ConnectTimeoutException; + +} diff --git a/httpclient/src/main/java/org/apache/http/conn/socket/LayeredConnectionSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/socket/LayeredConnectionSocketFactory.java new file mode 100644 index 000000000..3f4e2a9af --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/conn/socket/LayeredConnectionSocketFactory.java @@ -0,0 +1,63 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.conn.socket; + +import java.io.IOException; +import java.net.Socket; +import java.net.UnknownHostException; + +import org.apache.http.protocol.HttpContext; + +/** + * Extended {@link ConnectionSocketFactory} interface for layered sockets such as SSL/TLS. + * + * @since 4.3 + */ +public interface LayeredConnectionSocketFactory extends ConnectionSocketFactory { + + /** + * Returns a socket connected to the given host that is layered over an + * existing socket. Used primarily for creating secure sockets through + * proxies. + * + * @param socket the existing socket + * @param target the name of the target host. + * @param port the port to connect to on the target host. + * @param context the actual HTTP context. + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + */ + Socket createLayeredSocket( + Socket socket, + String target, + int port, + HttpContext context) throws IOException, UnknownHostException; + +} diff --git a/httpclient/src/main/java/org/apache/http/conn/socket/PlainSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/socket/PlainSocketFactory.java new file mode 100644 index 000000000..3d8dd2a34 --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/conn/socket/PlainSocketFactory.java @@ -0,0 +1,91 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.conn.socket; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketTimeoutException; + +import org.apache.http.HttpHost; +import org.apache.http.annotation.Immutable; +import org.apache.http.config.SocketConfig; +import org.apache.http.conn.ConnectTimeoutException; +import org.apache.http.protocol.HttpContext; + +/** + * The default class for creating plain (unencrypted) sockets. + * + * @since 4.3 + */ +@Immutable +public class PlainSocketFactory implements ConnectionSocketFactory { + + public static final PlainSocketFactory INSTANCE = new PlainSocketFactory(); + + public static PlainSocketFactory getSocketFactory() { + return INSTANCE; + } + + public PlainSocketFactory() { + super(); + } + + public Socket createSocket(final HttpContext context) throws IOException { + return new Socket(); + } + + public Socket connectSocket( + final int connectTimeout, + final Socket socket, + final SocketConfig config, + final HttpHost host, + final InetSocketAddress remoteAddress, + final InetSocketAddress localAddress, + final HttpContext context) throws IOException, ConnectTimeoutException { + Socket sock = socket != null ? socket : createSocket(context); + SocketConfig sconf = config != null ? config : SocketConfig.DEFAULT; + if (localAddress != null) { + sock.setReuseAddress(sconf.isSoReuseAddress()); + sock.bind(localAddress); + } + try { + sock.setSoTimeout(sconf.getSoTimeout()); + sock.connect(remoteAddress, connectTimeout); + } catch (SocketTimeoutException ex) { + throw new ConnectTimeoutException(host, remoteAddress); + } + sock.setTcpNoDelay(sconf.isTcpNoDelay()); + int linger = sconf.getSoLinger(); + if (linger >= 0) { + sock.setSoLinger(linger > 0, linger); + } + return sock; + } + +} diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLSocketFactory.java b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLSocketFactory.java index 94a4aea4f..0a66ed522 100644 --- a/httpclient/src/main/java/org/apache/http/conn/ssl/SSLSocketFactory.java +++ b/httpclient/src/main/java/org/apache/http/conn/ssl/SSLSocketFactory.java @@ -30,14 +30,19 @@ package org.apache.http.conn.ssl; import org.apache.http.HttpHost; import org.apache.http.annotation.ThreadSafe; +import org.apache.http.config.SocketConfig; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.HttpInetSocketAddress; import org.apache.http.conn.scheme.HostNameResolver; import org.apache.http.conn.scheme.LayeredSchemeSocketFactory; import org.apache.http.conn.scheme.LayeredSocketFactory; import org.apache.http.conn.scheme.SchemeLayeredSocketFactory; +import org.apache.http.conn.socket.LayeredConnectionSocketFactory; +import org.apache.http.conn.socket.PlainSocketFactory; import org.apache.http.params.HttpConnectionParams; +import org.apache.http.params.HttpParamConfig; import org.apache.http.params.HttpParams; +import org.apache.http.protocol.HttpContext; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; @@ -53,7 +58,6 @@ import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; -import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStore; @@ -84,14 +88,6 @@ import java.security.cert.CertificateException; * {@link TrustStrategy}. This interface is primarily intended for allowing self-signed * certificates to be accepted as trusted without having to add them to the trust-store file. *

- * The following parameters can be used to customize the behavior of this - * class: - *

    - *
  • {@link org.apache.http.params.CoreConnectionPNames#CONNECTION_TIMEOUT}
  • - *
  • {@link org.apache.http.params.CoreConnectionPNames#SO_TIMEOUT}
  • - *
  • {@link org.apache.http.params.CoreConnectionPNames#SO_REUSEADDR}
  • - *
- *

* SSLSocketFactory will enable client authentication when supplied with * a {@link KeyStore key-store} file containing a private key/public certificate * pair. The client secure socket will use the private key to authenticate @@ -147,7 +143,7 @@ import java.security.cert.CertificateException; */ @SuppressWarnings("deprecation") @ThreadSafe -public class SSLSocketFactory implements SchemeLayeredSocketFactory, +public class SSLSocketFactory implements LayeredConnectionSocketFactory, SchemeLayeredSocketFactory, LayeredSchemeSocketFactory, LayeredSocketFactory { public static final String TLS = "TLS"; @@ -242,7 +238,7 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory, sslcontext.init(keymanagers, trustmanagers, random); return sslcontext; } - + private static SSLContext createSystemSSLContext( String algorithm, final SecureRandom random) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, @@ -370,7 +366,8 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory, } /** - * @deprecated Use {@link #SSLSocketFactory(String, KeyStore, String, KeyStore, SecureRandom, X509HostnameVerifier)} + * @deprecated (4.1) Use {@link #SSLSocketFactory(String, KeyStore, String, KeyStore, + * SecureRandom, X509HostnameVerifier)} */ @Deprecated public SSLSocketFactory( @@ -464,7 +461,7 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory, } /** - * @deprecated Use {@link #SSLSocketFactory(SSLContext)} + * @deprecated (4.1) Use {@link #SSLSocketFactory(SSLContext)} */ @Deprecated public SSLSocketFactory( @@ -493,7 +490,7 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory, * @since 4.2 */ public SSLSocketFactory( - final javax.net.ssl.SSLSocketFactory socketfactory, + final javax.net.ssl.SSLSocketFactory socketfactory, final X509HostnameVerifier hostnameVerifier) { if (socketfactory == null) { throw new IllegalArgumentException("SSL socket factory may not be null"); @@ -507,23 +504,29 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory, * @param params Optional parameters. Parameters passed to this method will have no effect. * This method will create a unconnected instance of {@link Socket} class. * @since 4.1 + * + * @deprecated (4.3) use {@link #createSocket(HttpContext)} */ + @Deprecated public Socket createSocket(final HttpParams params) throws IOException { - SSLSocket sock = (SSLSocket) this.socketfactory.createSocket(); - prepareSocket(sock); - return sock; + return createSocket((HttpContext) null); } + /** + * @deprecated (4.1) use {@link #createSocket(HttpParams)} + */ @Deprecated public Socket createSocket() throws IOException { - SSLSocket sock = (SSLSocket) this.socketfactory.createSocket(); - prepareSocket(sock); - return sock; + return createSocket((HttpContext) null); } /** * @since 4.1 + * + * @deprecated (4.3) use {@link #connectSocket(Socket, SocketConfig, HttpHost, + * InetSocketAddress, InetSocketAddress, HttpContext)} */ + @Deprecated public Socket connectSocket( final Socket socket, final InetSocketAddress remoteAddress, @@ -535,52 +538,17 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory, if (params == null) { throw new IllegalArgumentException("HTTP parameters may not be null"); } - Socket sock = socket != null ? socket : this.socketfactory.createSocket(); - if (localAddress != null) { - sock.setReuseAddress(HttpConnectionParams.getSoReuseaddr(params)); - sock.bind(localAddress); - } - - int connTimeout = HttpConnectionParams.getConnectionTimeout(params); - int soTimeout = HttpConnectionParams.getSoTimeout(params); - - try { - sock.setSoTimeout(soTimeout); - sock.connect(remoteAddress, connTimeout); - } catch (SocketTimeoutException ex) { - throw new ConnectTimeoutException("Connect to " + remoteAddress + " timed out"); - } - - String hostname; + HttpHost host; if (remoteAddress instanceof HttpInetSocketAddress) { - hostname = ((HttpInetSocketAddress) remoteAddress).getHttpHost().getHostName(); + host = ((HttpInetSocketAddress) remoteAddress).getHttpHost(); } else { - hostname = remoteAddress.getHostName(); + host = new HttpHost(remoteAddress.getHostName(), remoteAddress.getPort(), "https"); } - - SSLSocket sslsock; - // Setup SSL layering if necessary - if (sock instanceof SSLSocket) { - sslsock = (SSLSocket) sock; - } else { - int port = remoteAddress.getPort(); - sslsock = (SSLSocket) this.socketfactory.createSocket(sock, hostname, port, true); - prepareSocket(sslsock); - } - if (this.hostnameVerifier != null) { - try { - this.hostnameVerifier.verify(hostname, sslsock); - // verifyHostName() didn't blowup - good! - } catch (IOException iox) { - // close the socket before re-throwing the exception - try { sslsock.close(); } catch (Exception x) { /*ignore*/ } - throw iox; - } - } - return sslsock; + int connectTimeout = HttpConnectionParams.getConnectionTimeout(params); + SocketConfig config = HttpParamConfig.getSocketConfig(params); + return connectSocket(connectTimeout, socket, config, host, remoteAddress, localAddress, null); } - /** * Checks whether a socket connection is secure. * This factory creates TLS/SSL socket connections @@ -594,7 +562,10 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory, * @return true * * @throws IllegalArgumentException if the argument is invalid + * + * @deprecated (4.3) no longer used. */ + @Deprecated public boolean isSecure(final Socket sock) throws IllegalArgumentException { if (sock == null) { throw new IllegalArgumentException("Socket may not be null"); @@ -612,48 +583,33 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory, /** * @since 4.2 + * + * @deprecated (4.3) use {@link #createLayeredSocket(Socket, String, int, HttpContext)} */ + @Deprecated public Socket createLayeredSocket( final Socket socket, final String host, final int port, final HttpParams params) throws IOException, UnknownHostException { - SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket( - socket, - host, - port, - true); - prepareSocket(sslSocket); - if (this.hostnameVerifier != null) { - this.hostnameVerifier.verify(host, sslSocket); - } - // verifyHostName() didn't blowup - good! - return sslSocket; + return createLayeredSocket(socket, host, port, (HttpContext) null); } /** - * @deprecated use {@link #createLayeredSocket(Socket, String, int, HttpParams)} + * @deprecated (4.1) use {@link #createLayeredSocket(Socket, String, int, HttpParams)} */ @Deprecated - public Socket createLayeredSocket( + public Socket createLayeredSocket( final Socket socket, final String host, final int port, final boolean autoClose) throws IOException, UnknownHostException { - SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket( - socket, - host, - port, - autoClose - ); - prepareSocket(sslSocket); - if (this.hostnameVerifier != null) { - this.hostnameVerifier.verify(host, sslSocket); - } - // verifyHostName() didn't blowup - good! - return sslSocket; + return createLayeredSocket(socket, host, port, (HttpContext) null); } + /** + * @deprecated (4.1) use constructor. + */ @Deprecated public void setHostnameVerifier(X509HostnameVerifier hostnameVerifier) { if ( hostnameVerifier == null ) { @@ -667,34 +623,36 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory, } /** - * @deprecated Use {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams)} + * @deprecated (4.1) Use {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, + * HttpParams)} */ @Deprecated public Socket connectSocket( final Socket socket, final String host, int port, - final InetAddress localAddress, int localPort, + final InetAddress local, int localPort, final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException { - InetSocketAddress local = null; - if (localAddress != null || localPort > 0) { + InetAddress remote; + if (this.nameResolver != null) { + remote = this.nameResolver.resolve(host); + } else { + remote = InetAddress.getByName(host); + } + InetSocketAddress localAddress = null; + if (local != null || localPort > 0) { // we need to bind explicitly if (localPort < 0) { localPort = 0; // indicates "any" } - local = new InetSocketAddress(localAddress, localPort); + localAddress = new InetSocketAddress(local, localPort); } - InetAddress remoteAddress; - if (this.nameResolver != null) { - remoteAddress = this.nameResolver.resolve(host); - } else { - remoteAddress = InetAddress.getByName(host); - } - InetSocketAddress remote = new HttpInetSocketAddress(new HttpHost(host, port), remoteAddress, port); - return connectSocket(socket, remote, local, params); + InetSocketAddress remoteAddress = new HttpInetSocketAddress( + new HttpHost(host, port), remote, port); + return connectSocket(socket, remoteAddress, localAddress, params); } /** - * @deprecated Use {@link #createLayeredSocket(Socket, String, int, boolean)} + * @deprecated (4.1) Use {@link #createLayeredSocket(Socket, String, int, boolean)} */ @Deprecated public Socket createSocket( @@ -715,4 +673,75 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory, */ protected void prepareSocket(final SSLSocket socket) throws IOException { } + + /** + * {@inheritDoc} + * + * @since 4.3 + */ + public Socket createSocket(final HttpContext context) throws IOException { + SSLSocket sock = (SSLSocket) this.socketfactory.createSocket(); + prepareSocket(sock); + return sock; + } + + /** + * {@inheritDoc} + * + * @since 4.3 + */ + public Socket connectSocket( + final int connectTimeout, + final Socket socket, + final SocketConfig config, + final HttpHost host, + final InetSocketAddress remoteAddress, + final InetSocketAddress localAddress, + final HttpContext context) throws IOException, ConnectTimeoutException { + if (host == null) { + throw new IllegalArgumentException("HTTP host may not be null"); + } + if (remoteAddress == null) { + throw new IllegalArgumentException("Remote address may not be null"); + } + Socket sock = socket != null ? socket : createSocket(context); + PlainSocketFactory.INSTANCE.connectSocket( + connectTimeout, socket, config, host, remoteAddress, localAddress, context); + // Setup SSL layering if necessary + if (sock instanceof SSLSocket) { + verifyHostname((SSLSocket) sock, host.getHostName()); + } else { + sock = createLayeredSocket(sock, host.getHostName(), remoteAddress.getPort(), context); + } + return sock; + } + + public Socket createLayeredSocket( + final Socket socket, + final String target, + int port, + final HttpContext context) throws IOException, UnknownHostException { + SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket( + socket, + target, + port, + true); + prepareSocket(sslSocket); + verifyHostname(sslSocket, target); + return sslSocket; + } + + private void verifyHostname(final SSLSocket sslsock, final String hostname) throws IOException { + if (this.hostnameVerifier != null) { + try { + this.hostnameVerifier.verify(hostname, sslsock); + // verifyHostName() didn't blowup - good! + } catch (IOException iox) { + // close the socket before re-throwing the exception + try { sslsock.close(); } catch (Exception x) { /*ignore*/ } + throw iox; + } + } + } + }