Make connectUsingConfiguration more robust

If 'return' is not reached, then always throw a
ConnectionException.

Also make it clear that populateHostAddresses adds at least one address.
This commit is contained in:
Florian Schmaus 2015-01-25 00:05:06 +01:00
parent e6045c6593
commit d9c97fabfb
2 changed files with 25 additions and 20 deletions

View File

@ -570,7 +570,11 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
protected List<HostAddress> hostAddresses; protected List<HostAddress> hostAddresses;
protected void populateHostAddresses() throws Exception { /**
* Populates {@link #hostAddresses} with at least one host address.
*
*/
protected void populateHostAddresses() {
// N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName // N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName
if (config.host != null) { if (config.host != null) {
hostAddresses = new ArrayList<HostAddress>(1); hostAddresses = new ArrayList<HostAddress>(1);
@ -580,6 +584,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
} else { } else {
hostAddresses = DNSUtil.resolveXMPPDomain(config.serviceName); hostAddresses = DNSUtil.resolveXMPPDomain(config.serviceName);
} }
// If we reach this, then hostAddresses *must not* be empty, i.e. there is at least one host added, either the
// config.host one or the host representing the service name by DNSUtil
assert(!hostAddresses.isEmpty());
} }
protected Lock getConnectionLock() { protected Lock getConnectionLock() {

View File

@ -99,6 +99,7 @@ import java.lang.reflect.Constructor;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException; import java.security.KeyStoreException;
@ -516,25 +517,24 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
} }
private void connectUsingConfiguration(XMPPTCPConnectionConfiguration config) throws SmackException, IOException { private void connectUsingConfiguration(XMPPTCPConnectionConfiguration config) throws SmackException, IOException {
try { populateHostAddresses();
populateHostAddresses();
}
catch (Exception e) {
throw new SmackException(e);
}
Iterator<HostAddress> it = hostAddresses.iterator();
List<HostAddress> failedAddresses = new LinkedList<HostAddress>(); List<HostAddress> failedAddresses = new LinkedList<HostAddress>();
SocketFactory socketFactory = config.getSocketFactory(); SocketFactory socketFactory = config.getSocketFactory();
if (socketFactory == null) { if (socketFactory == null) {
socketFactory = SocketFactory.getDefault(); socketFactory = SocketFactory.getDefault();
} }
outerloop: while (it.hasNext()) { for (HostAddress hostAddress : hostAddresses) {
HostAddress hostAddress = it.next();
String host = hostAddress.getFQDN(); String host = hostAddress.getFQDN();
int port = hostAddress.getPort(); int port = hostAddress.getPort();
socket = socketFactory.createSocket(); socket = socketFactory.createSocket();
try { try {
Iterator<InetAddress> inetAddresses = Arrays.asList(InetAddress.getAllByName(host)).iterator(); Iterator<InetAddress> inetAddresses = Arrays.asList(InetAddress.getAllByName(host)).iterator();
if (!inetAddresses.hasNext()) {
// This should not happen
LOGGER.warning("InetAddress.getAllByName() returned empty result array.");
throw new UnknownHostException(host);
}
innerloop: while (inetAddresses.hasNext()) { innerloop: while (inetAddresses.hasNext()) {
final InetAddress inetAddress = inetAddresses.next(); final InetAddress inetAddress = inetAddresses.next();
final String inetAddressAndPort = inetAddress + "at port " + port; final String inetAddressAndPort = inetAddress + "at port " + port;
@ -549,25 +549,21 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
} }
} }
LOGGER.finer("Established TCP connection to " + inetAddressAndPort); LOGGER.finer("Established TCP connection to " + inetAddressAndPort);
// We found a host to connect to, break here // We found a host to connect to, return here
this.host = host; this.host = host;
this.port = port; this.port = port;
break outerloop; return;
} }
} }
catch (Exception e) { catch (Exception e) {
hostAddress.setException(e); hostAddress.setException(e);
failedAddresses.add(hostAddress); failedAddresses.add(hostAddress);
if (!it.hasNext()) {
// There are no more host addresses to try
// throw an exception and report all tried
// HostAddresses in the exception
throw ConnectionException.from(failedAddresses);
}
} }
} }
socketClosed = false; // There are no more host addresses to try
initConnection(); // throw an exception and report all tried
// HostAddresses in the exception
throw ConnectionException.from(failedAddresses);
} }
/** /**
@ -822,6 +818,8 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
throwAlreadyConnectedExceptionIfAppropriate(); throwAlreadyConnectedExceptionIfAppropriate();
// Establishes the connection, readers and writers // Establishes the connection, readers and writers
connectUsingConfiguration(config); connectUsingConfiguration(config);
socketClosed = false;
initConnection();
// Wait with SASL auth until the SASL mechanisms have been received // Wait with SASL auth until the SASL mechanisms have been received
saslFeatureReceived.checkIfSuccessOrWaitOrThrow(); saslFeatureReceived.checkIfSuccessOrWaitOrThrow();