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 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
if (config.host != null) {
hostAddresses = new ArrayList<HostAddress>(1);
@ -580,6 +584,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
} else {
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() {

View File

@ -99,6 +99,7 @@ import java.lang.reflect.Constructor;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
@ -516,25 +517,24 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
}
private void connectUsingConfiguration(XMPPTCPConnectionConfiguration config) throws SmackException, IOException {
try {
populateHostAddresses();
}
catch (Exception e) {
throw new SmackException(e);
}
Iterator<HostAddress> it = hostAddresses.iterator();
populateHostAddresses();
List<HostAddress> failedAddresses = new LinkedList<HostAddress>();
SocketFactory socketFactory = config.getSocketFactory();
if (socketFactory == null) {
socketFactory = SocketFactory.getDefault();
}
outerloop: while (it.hasNext()) {
HostAddress hostAddress = it.next();
for (HostAddress hostAddress : hostAddresses) {
String host = hostAddress.getFQDN();
int port = hostAddress.getPort();
socket = socketFactory.createSocket();
try {
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()) {
final InetAddress inetAddress = inetAddresses.next();
final String inetAddressAndPort = inetAddress + "at port " + port;
@ -549,25 +549,21 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
}
}
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.port = port;
break outerloop;
return;
}
}
catch (Exception e) {
hostAddress.setException(e);
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;
initConnection();
// There are no more host addresses to try
// 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();
// Establishes the connection, readers and writers
connectUsingConfiguration(config);
socketClosed = false;
initConnection();
// Wait with SASL auth until the SASL mechanisms have been received
saslFeatureReceived.checkIfSuccessOrWaitOrThrow();