More robust localhost resolution

Ensure the resolved localhost can be bound and connected actually
This commit is contained in:
Trustin Lee 2012-11-10 08:45:07 +09:00
parent b4f796c5e3
commit 0b30bf613d
2 changed files with 54 additions and 20 deletions

View File

@ -20,10 +20,13 @@ import io.netty.logging.InternalLoggerFactory;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException; import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration; import java.util.Enumeration;
/** /**
@ -60,30 +63,26 @@ public final class NetworkConstants {
static { static {
//Start the process of discovering localhost //Start the process of discovering localhost
InetAddress localhost = null; InetAddress localhost;
try { try {
//Let's start by getting localhost automatically
localhost = InetAddress.getLocalHost(); localhost = InetAddress.getLocalHost();
} catch (UnknownHostException e) { validateHost(localhost);
//No? That's okay. } catch (IOException e) {
// The default local host names did not work. Try hard-coded IPv4 address.
try { try {
//Try to force an IPv4 localhost address
localhost = InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 }); localhost = InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 });
} catch (UnknownHostException e1) { validateHost(localhost);
//No? Okay. You must be using IPv6 } catch (IOException e1) {
// The hard-coded IPv4 address did not work. Try hard coded IPv6 address.
try { try {
//Try to force an IPv6 localhost address localhost = InetAddress.getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 });
localhost = InetAddress.getByAddress( validateHost(localhost);
new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }); } catch (IOException e2) {
} catch (UnknownHostException e2) { throw new Error("Failed to resolve localhost - incorrect network configuration?", e2);
//No? Okay.
logger.error("Failed to resolve localhost - Incorrect network configuration?", e2);
} }
} }
} }
//Set the localhost constant
LOCALHOST = localhost; LOCALHOST = localhost;
//Prepare to get the local NetworkInterface //Prepare to get the local NetworkInterface
@ -143,6 +142,41 @@ public final class NetworkConstants {
SOMAXCONN = somaxconn; SOMAXCONN = somaxconn;
} }
private static void validateHost(InetAddress host) throws IOException {
ServerSocket ss = null;
Socket s1 = null;
Socket s2 = null;
try {
ss = new ServerSocket();
ss.setReuseAddress(false);
ss.bind(new InetSocketAddress(host, 0));
s1 = new Socket(host, ss.getLocalPort());
s2 = ss.accept();
} finally {
if (s2 != null) {
try {
s2.close();
} catch (IOException e) {
// Ignore
}
}
if (s1 != null) {
try {
s1.close();
} catch (IOException e) {
// Ignore
}
}
if (ss != null) {
try {
ss.close();
} catch (IOException e) {
// Ignore
}
}
}
}
/** /**
* A constructor to stop this class being constructed. * A constructor to stop this class being constructed.
*/ */

View File

@ -30,7 +30,7 @@ public final class TestUtils {
private static final int NUM_CANDIDATES = END_PORT - START_PORT; private static final int NUM_CANDIDATES = END_PORT - START_PORT;
private static final List<Integer> PORTS = new ArrayList<Integer>(); private static final List<Integer> PORTS = new ArrayList<Integer>();
private static Iterator<Integer> PORTS_ITERATOR; private static Iterator<Integer> portIterator;
static { static {
for (int i = START_PORT; i < END_PORT; i ++) { for (int i = START_PORT; i < END_PORT; i ++) {
@ -40,10 +40,10 @@ public final class TestUtils {
} }
private static int nextCandidatePort() { private static int nextCandidatePort() {
if (PORTS_ITERATOR == null || !PORTS_ITERATOR.hasNext()) { if (portIterator == null || !portIterator.hasNext()) {
PORTS_ITERATOR = PORTS.iterator(); portIterator = PORTS.iterator();
} }
return PORTS_ITERATOR.next(); return portIterator.next();
} }
/** /**