mirror of
https://github.com/apache/httpcomponents-client.git
synced 2025-02-16 23:16:33 +00:00
This patch effectively reverts HTTPCLIENT-643 changes. Multihome fail-over mechanism simply cannot be properly implemented at the socket factory level. A failure in the connect method can leave the socket in a inconsistent state on some platforms (Mac OS), making it impossible to connect the same socket to a different address
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@631713 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
63035b081b
commit
b055442d4b
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* $HeadURL$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* ====================================================================
|
||||
* 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
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.http.conn;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.http.params.HttpConnectionParams;
|
||||
import org.apache.http.params.HttpParams;
|
||||
|
||||
public final class MultihomePlainSocketFactory implements SocketFactory {
|
||||
|
||||
/**
|
||||
* The factory singleton.
|
||||
*/
|
||||
private static final
|
||||
MultihomePlainSocketFactory DEFAULT_FACTORY = new MultihomePlainSocketFactory();
|
||||
|
||||
/**
|
||||
* Gets the singleton instance of this class.
|
||||
* @return the one and only plain socket factory
|
||||
*/
|
||||
public static final MultihomePlainSocketFactory getSocketFactory() {
|
||||
return DEFAULT_FACTORY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restricted default constructor.
|
||||
*/
|
||||
private MultihomePlainSocketFactory() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
// non-javadoc, see interface org.apache.http.conn.SocketFactory
|
||||
public Socket createSocket() {
|
||||
return new Socket();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to connects the socket to any of the {@link InetAddress}es the
|
||||
* given host name resolves to. If connection to all addresses fail, the
|
||||
* last I/O exception is propagated to the caller.
|
||||
*
|
||||
* @param sock socket to connect to any of the given addresses
|
||||
* @param host Host name to connect to
|
||||
* @param port the port to connect to
|
||||
* @param localAddress local address
|
||||
* @param localPort local port
|
||||
* @param params HTTP parameters
|
||||
*
|
||||
* @throws IOException if an error occurs during the connection
|
||||
* @throws SocketTimeoutException if timeout expires before connecting
|
||||
*/
|
||||
public Socket connectSocket(Socket sock, String host, int port,
|
||||
InetAddress localAddress, int localPort,
|
||||
HttpParams params)
|
||||
throws IOException {
|
||||
|
||||
if (host == null) {
|
||||
throw new IllegalArgumentException("Target host may not be null.");
|
||||
}
|
||||
if (params == null) {
|
||||
throw new IllegalArgumentException("Parameters may not be null.");
|
||||
}
|
||||
|
||||
if (sock == null)
|
||||
sock = createSocket();
|
||||
|
||||
if ((localAddress != null) || (localPort > 0)) {
|
||||
|
||||
// we need to bind explicitly
|
||||
if (localPort < 0)
|
||||
localPort = 0; // indicates "any"
|
||||
|
||||
InetSocketAddress isa =
|
||||
new InetSocketAddress(localAddress, localPort);
|
||||
sock.bind(isa);
|
||||
}
|
||||
|
||||
int timeout = HttpConnectionParams.getConnectionTimeout(params);
|
||||
|
||||
InetAddress[] inetadrs = InetAddress.getAllByName(host);
|
||||
List<InetAddress> addresses = new ArrayList<InetAddress>(inetadrs.length);
|
||||
for (InetAddress inetadr: inetadrs) {
|
||||
addresses.add(inetadr);
|
||||
}
|
||||
Collections.shuffle(addresses);
|
||||
|
||||
IOException lastEx = null;
|
||||
for (InetAddress address: addresses) {
|
||||
try {
|
||||
sock.connect(new InetSocketAddress(address, port), timeout);
|
||||
break;
|
||||
} catch (SocketTimeoutException ex) {
|
||||
throw ex;
|
||||
} catch (IOException ex) {
|
||||
// create new socket
|
||||
sock = new Socket();
|
||||
// keep the last exception and retry
|
||||
lastEx = ex;
|
||||
}
|
||||
}
|
||||
if (lastEx != null) {
|
||||
throw lastEx;
|
||||
}
|
||||
return sock;
|
||||
} // connectSocket
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether a socket connection is secure.
|
||||
* This factory creates plain socket connections
|
||||
* which are not considered secure.
|
||||
*
|
||||
* @param sock the connected socket
|
||||
*
|
||||
* @return <code>false</code>
|
||||
*
|
||||
* @throws IllegalArgumentException if the argument is invalid
|
||||
*/
|
||||
public final boolean isSecure(Socket sock)
|
||||
throws IllegalArgumentException {
|
||||
|
||||
if (sock == null) {
|
||||
throw new IllegalArgumentException("Socket may not be null.");
|
||||
}
|
||||
// This class check assumes that createSocket() calls the constructor
|
||||
// directly. If it was using javax.net.SocketFactory, we couldn't make
|
||||
// an assumption about the socket class here.
|
||||
if (sock.getClass() != Socket.class) {
|
||||
throw new IllegalArgumentException
|
||||
("Socket not created by this factory.");
|
||||
}
|
||||
// This check is performed last since it calls a method implemented
|
||||
// by the argument object. getClass() is final in java.lang.Object.
|
||||
if (sock.isClosed()) {
|
||||
throw new IllegalArgumentException("Socket is closed.");
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
} // isSecure
|
||||
|
||||
|
||||
/**
|
||||
* Compares this factory with an object.
|
||||
* There is only one instance of this class.
|
||||
*
|
||||
* @param obj the object to compare with
|
||||
*
|
||||
* @return iff the argument is this object
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (obj == this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a hash code for this object.
|
||||
* All instances of this class have the same hash code.
|
||||
* There is only one instance of this class.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return PlainSocketFactory.class.hashCode();
|
||||
}
|
||||
|
||||
}
|
@ -36,7 +36,6 @@
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.apache.http.conn.util.SocketUtils;
|
||||
import org.apache.http.params.HttpConnectionParams;
|
||||
import org.apache.http.params.HttpParams;
|
||||
|
||||
@ -106,7 +105,7 @@ public Socket connectSocket(Socket sock, String host, int port,
|
||||
|
||||
int timeout = HttpConnectionParams.getConnectionTimeout(params);
|
||||
|
||||
SocketUtils.connect(sock, host, port, timeout);
|
||||
sock.connect(new InetSocketAddress(host, port), timeout);
|
||||
|
||||
return sock;
|
||||
|
||||
|
@ -32,7 +32,6 @@
|
||||
package org.apache.http.conn.ssl;
|
||||
|
||||
import org.apache.http.conn.LayeredSocketFactory;
|
||||
import org.apache.http.conn.util.SocketUtils;
|
||||
import org.apache.http.params.HttpConnectionParams;
|
||||
import org.apache.http.params.HttpParams;
|
||||
|
||||
@ -290,7 +289,7 @@ public Socket connectSocket(
|
||||
int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
|
||||
int soTimeout = HttpConnectionParams.getSoTimeout(params);
|
||||
|
||||
SocketUtils.connect(sock, host, port, connTimeout);
|
||||
sock.connect(new InetSocketAddress(host, port), connTimeout);
|
||||
|
||||
sslock.setSoTimeout(soTimeout);
|
||||
try {
|
||||
|
@ -1,118 +0,0 @@
|
||||
/*
|
||||
* $HeadURL:$
|
||||
* $Revision:$
|
||||
* $Date:$
|
||||
*
|
||||
* ====================================================================
|
||||
* 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
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.http.conn.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class SocketUtils {
|
||||
|
||||
/**
|
||||
* Attempts to connects the socket to any of the {@link InetAddress}es the
|
||||
* given host name resolves to. If connection to all addresses fail, the
|
||||
* last I/O exception is propagated to the caller.
|
||||
*
|
||||
* @param sock socket to connect to any of the given addresses
|
||||
* @param hostname Host name to connect to
|
||||
* @param port the port to connect to
|
||||
* @param timeout connection timeout
|
||||
*
|
||||
* @throws IOException if an error occurs during the connection
|
||||
* @throws SocketTimeoutException if timeout expires before connecting
|
||||
*/
|
||||
public static void connect(
|
||||
final Socket sock,
|
||||
final String hostname,
|
||||
int port,
|
||||
int timeout) throws IOException {
|
||||
|
||||
InetAddress[] adrs = InetAddress.getAllByName(hostname);
|
||||
List<InetAddress> list = new ArrayList<InetAddress>(adrs.length);
|
||||
for (InetAddress adr: adrs) {
|
||||
list.add(adr);
|
||||
}
|
||||
Collections.shuffle(list);
|
||||
connect(sock, list, port, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to connects the socket to any of the {@link InetAddress}es given as a
|
||||
* parameter, whichever succeeds first. If connection to all addresses fail, the
|
||||
* last I/O exception is propagated to the caller.
|
||||
*
|
||||
* @param sock socket to connect to any of the given addresses
|
||||
* @param addresses array of addresses
|
||||
* @param port the port to connect to
|
||||
* @param timeout connection timeout
|
||||
*
|
||||
* @throws IOException if an error occurs during the connection
|
||||
* @throws SocketTimeoutException if timeout expires before connecting
|
||||
*/
|
||||
public static void connect(
|
||||
final Socket sock,
|
||||
final List<InetAddress> addresses,
|
||||
int port,
|
||||
int timeout) throws IOException {
|
||||
if (sock == null) {
|
||||
throw new IllegalArgumentException("Socket may not be null");
|
||||
}
|
||||
if (addresses == null) {
|
||||
throw new IllegalArgumentException("List of addresses may not be null");
|
||||
}
|
||||
if (addresses.isEmpty()) {
|
||||
throw new IllegalArgumentException("List of addresses may not be empty");
|
||||
}
|
||||
|
||||
IOException lastEx = null;
|
||||
for (InetAddress address: addresses) {
|
||||
try {
|
||||
sock.connect(new InetSocketAddress(address, port), timeout);
|
||||
return;
|
||||
} catch (SocketTimeoutException ex) {
|
||||
throw ex;
|
||||
} catch (IOException ex) {
|
||||
// keep the last exception and retry
|
||||
lastEx = ex;
|
||||
}
|
||||
}
|
||||
if (lastEx != null) {
|
||||
throw lastEx;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user