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: - *
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;
+ }
+ }
+ }
+
}