More robust localhost resolution
Ensure the resolved localhost can be bound and connected actually
This commit is contained in:
parent
922a8dbb47
commit
6be84510dc
@ -15,23 +15,12 @@
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.frame;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.jboss.netty.bootstrap.ClientBootstrap;
|
||||
import org.jboss.netty.bootstrap.ServerBootstrap;
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelFactory;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.channel.ChannelStateEvent;
|
||||
import org.jboss.netty.channel.ExceptionEvent;
|
||||
@ -43,6 +32,16 @@ import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public abstract class AbstractSocketFixedLengthEchoTest {
|
||||
|
||||
private static final Random random = new Random();
|
||||
@ -83,10 +82,8 @@ public abstract class AbstractSocketFixedLengthEchoTest {
|
||||
Channel sc = sb.bind(new InetSocketAddress(0));
|
||||
int port = ((InetSocketAddress) sc.getLocalAddress()).getPort();
|
||||
|
||||
ChannelFuture ccf = cb.connect(new InetSocketAddress(TestUtil.getLocalHost(), port));
|
||||
assertTrue(ccf.awaitUninterruptibly().isSuccess());
|
||||
|
||||
Channel cc = ccf.getChannel();
|
||||
Channel cc = cb.connect(
|
||||
new InetSocketAddress(TestUtil.getLocalHost(), port)).syncUninterruptibly().getChannel();
|
||||
for (int i = 0; i < data.length;) {
|
||||
int length = Math.min(random.nextInt(1024 * 3), data.length - i);
|
||||
cc.write(ChannelBuffers.wrappedBuffer(data, i, length));
|
||||
|
@ -15,34 +15,43 @@
|
||||
*/
|
||||
package org.jboss.netty.util;
|
||||
|
||||
import org.junit.Ignore;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
@org.junit.Ignore
|
||||
@Ignore
|
||||
public final class TestUtil {
|
||||
|
||||
private static final InetAddress LOCALHOST;
|
||||
private final static int START_PORT = 20000;
|
||||
private final static int END_PORT = 30000;
|
||||
|
||||
static {
|
||||
InetAddress localhost = null;
|
||||
InetAddress localhost;
|
||||
try {
|
||||
localhost = InetAddress.getLocalHost();
|
||||
} catch (UnknownHostException e) {
|
||||
validateHost(localhost);
|
||||
} catch (IOException e) {
|
||||
// The default local host names did not work. Try hard-coded IPv4 address.
|
||||
try {
|
||||
localhost = InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 });
|
||||
} catch (UnknownHostException e1) {
|
||||
validateHost(localhost);
|
||||
} catch (IOException e1) {
|
||||
// The hard-coded IPv4 address did not work. Try hard coded IPv6 address.
|
||||
try {
|
||||
localhost = InetAddress.getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 });
|
||||
} catch (UnknownHostException e2) {
|
||||
System.err.println("Failed to get the localhost.");
|
||||
e2.printStackTrace();
|
||||
validateHost(localhost);
|
||||
} catch (IOException e2) {
|
||||
throw new Error("Failed to resolve localhost - incorrect network configuration?", e2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -50,6 +59,41 @@ public final class TestUtil {
|
||||
LOCALHOST = localhost;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static InetAddress getLocalHost() {
|
||||
// We cache this because some machine takes almost forever to return
|
||||
// from InetAddress.getLocalHost(). I think it's due to the incorrect
|
||||
@ -57,6 +101,26 @@ public final class TestUtil {
|
||||
return LOCALHOST;
|
||||
}
|
||||
|
||||
private static final int START_PORT = 32768;
|
||||
private static final int END_PORT = 65536;
|
||||
private static final int NUM_CANDIDATES = END_PORT - START_PORT;
|
||||
|
||||
private static final List<Integer> PORTS = new ArrayList<Integer>();
|
||||
private static Iterator<Integer> portIterator;
|
||||
|
||||
static {
|
||||
for (int i = START_PORT; i < END_PORT; i ++) {
|
||||
PORTS.add(i);
|
||||
}
|
||||
Collections.shuffle(PORTS);
|
||||
}
|
||||
|
||||
private static int nextCandidatePort() {
|
||||
if (portIterator == null || !portIterator.hasNext()) {
|
||||
portIterator = PORTS.iterator();
|
||||
}
|
||||
return portIterator.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a free port which can be used to bind to
|
||||
@ -64,19 +128,30 @@ public final class TestUtil {
|
||||
* @return port
|
||||
*/
|
||||
public static int getFreePort() {
|
||||
for(int start = START_PORT; start <= END_PORT; start++) {
|
||||
for (int i = 0; i < NUM_CANDIDATES; i ++) {
|
||||
int port = nextCandidatePort();
|
||||
try {
|
||||
ServerSocket socket = new ServerSocket(start);
|
||||
socket.setReuseAddress(true);
|
||||
socket.close();
|
||||
return start;
|
||||
// Ensure it is possible to bind on both wildcard and loopback.
|
||||
ServerSocket ss;
|
||||
ss = new ServerSocket();
|
||||
ss.setReuseAddress(false);
|
||||
ss.bind(new InetSocketAddress(port));
|
||||
ss.close();
|
||||
|
||||
ss = new ServerSocket();
|
||||
ss.setReuseAddress(false);
|
||||
ss.bind(new InetSocketAddress(LOCALHOST, port));
|
||||
ss.close();
|
||||
|
||||
return port;
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
}
|
||||
throw new RuntimeException("Unable to find a free port....");
|
||||
|
||||
throw new RuntimeException("unable to find a free port");
|
||||
}
|
||||
|
||||
private TestUtil() {
|
||||
// Unused
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user