Enhance the SocketAddress API and avoid name resolution when providing an IP host for server bind operations - fixes #3265 - fixes #3266

This commit is contained in:
Julien Viet
2020-01-28 13:41:37 +01:00
parent 4d336085fe
commit 8b05bb9e61
18 changed files with 317 additions and 82 deletions

View File

@@ -23,6 +23,7 @@ import java.net.InetSocketAddress;
* @author <a href="mailto:nmaurer@redhat.com">Norman Maurer</a>
*/
final class DatagramPacketImpl implements DatagramPacket {
private final InetSocketAddress sender;
private final Buffer buffer;
private SocketAddress senderAddress;
@@ -35,7 +36,7 @@ final class DatagramPacketImpl implements DatagramPacket {
@Override
public SocketAddress sender() {
if (senderAddress == null) {
senderAddress = new SocketAddressImpl(sender.getPort(), sender.getAddress().getHostAddress());
senderAddress = SocketAddress.inetSocketAddress(sender);
}
return senderAddress;
}

View File

@@ -243,13 +243,13 @@ public class DatagramSocketImpl implements DatagramSocket, MetricsProvider {
@Override
public DatagramSocket listen(int port, String address, Handler<AsyncResult<DatagramSocket>> handler) {
Objects.requireNonNull(handler, "no null handler accepted");
listen(new SocketAddressImpl(port, address)).setHandler(handler);
listen(SocketAddress.inetSocketAddress(port, address)).setHandler(handler);
return this;
}
@Override
public Future<DatagramSocket> listen(int port, String address) {
return listen(new SocketAddressImpl(port, address));
return listen(SocketAddress.inetSocketAddress(port, address));
}
@Override
@@ -350,7 +350,7 @@ public class DatagramSocketImpl implements DatagramSocket, MetricsProvider {
if (metrics != null) {
f2.addListener(fut -> {
if (fut.isSuccess()) {
metrics.bytesWritten(null, new SocketAddressImpl(port, host), packet.length());
metrics.bytesWritten(null, SocketAddress.inetSocketAddress(port, host), packet.length());
}
});
}

View File

@@ -119,7 +119,7 @@ class ConnectionManager {
int maxPoolSize = Math.max(client.getOptions().getMaxPoolSize(), client.getOptions().getHttp2MaxPoolSize());
String host;
int port;
if (server.path() == null) {
if (server.isInetSocket()) {
host = server.host();
port = server.port();
} else {

View File

@@ -223,7 +223,7 @@ public class HttpServerImpl implements HttpServer, Closeable, MetricsProvider {
}
listenContext = vertx.getOrCreateContext();
listening = true;
String host = address.host() != null ? address.host() : "localhost";
String host = address.isInetSocket() ? address.host() : "localhost";
int port = address.port();
List<HttpVersion> applicationProtocols = options.getAlpnVersions();
sslHelper.setApplicationProtocols(applicationProtocols);
@@ -236,7 +236,7 @@ public class HttpServerImpl implements HttpServer, Closeable, MetricsProvider {
serverChannelGroup = new DefaultChannelGroup("vertx-acceptor-channels", GlobalEventExecutor.INSTANCE);
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(vertx.getAcceptorEventLoopGroup(), availableWorkers);
applyConnectionOptions(address.path() != null, bootstrap);
applyConnectionOptions(address.isDomainSocket(), bootstrap);
sslHelper.validate(vertx);
String serverOrigin = (options.isSsl() ? "https" : "http") + "://" + host + ":" + port;
bootstrap.childHandler(childHandler(address, serverOrigin));

View File

@@ -11,9 +11,13 @@
package io.vertx.core.net;
import io.vertx.codegen.annotations.CacheReturn;
import io.vertx.codegen.annotations.GenIgnore;
import io.vertx.codegen.annotations.VertxGen;
import io.vertx.core.net.impl.SocketAddressImpl;
import java.net.InetSocketAddress;
/**
* The address of a socket, an inet socket address or a domain socket address.
* <p/>
@@ -28,9 +32,13 @@ public interface SocketAddress {
/**
* Create a inet socket address, {@code host} must be non {@code null} and {@code port} must be between {@code 0}
* and {@code 65536}.
* <br/>
* The {@code host} string can be an host name or an host address.
* <br/>
* No name resolution will be attempted.
*
* @param port the address port
* @param host the address host
* @param port the port
* @param host the host
* @return the created socket address
*/
static SocketAddress inetSocketAddress(int port, String host) {
@@ -38,7 +46,7 @@ public interface SocketAddress {
}
/**
* Create a domain socket address.
* Create a domain socket address from a {@code path}.
*
* @param path the address path
* @return the created socket address
@@ -48,18 +56,70 @@ public interface SocketAddress {
}
/**
* @return the address host or {@code null} for a domain socket
* Create a inet socket address from a Java {@link InetSocketAddress}.
* <br/>
* No name resolution will be attempted.
*
* @param address the address
* @return the created socket address
*/
@GenIgnore(GenIgnore.PERMITTED_TYPE)
static SocketAddress inetSocketAddress(InetSocketAddress address) {
return new SocketAddressImpl(address);
}
/**
* Returns the host name when available or the IP address in string representation.
* <br/>
* Domain socket address returns {@code null}.
*
* @return the host address
*/
@CacheReturn
String host();
/**
* Returns the host name when available or {@code null}
* <br/>
* Domain socket address returns {@code null}.
*
* @return the host name
*/
@CacheReturn
String hostName();
/**
* Returns the host IP address when available or {@code null} as a String.
* <br/>
* Domain socket address returns {@code null}.
*
* @return the host address
*/
@CacheReturn
String hostAddress();
/**
* @return the address port or {@code -1} for a domain socket
*/
@CacheReturn
int port();
/**
* @return the address path or {@code null} for a inet socket
* @return the domain socket path or {@code null} for a inet socket address.
*/
@CacheReturn
String path();
/**
* @return {@code true} for an inet socket address
*/
@CacheReturn
boolean isInetSocket();
/**
* @return {@code true} for an domain socket address
*/
@CacheReturn
boolean isDomainSocket();
}

View File

@@ -15,9 +15,13 @@ import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.util.concurrent.Promise;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.impl.VertxInternal;
import io.vertx.core.net.SocketAddress;
import java.net.InetAddress;
import java.net.InetSocketAddress;
/**
@@ -25,24 +29,18 @@ import java.net.InetSocketAddress;
*/
public class AsyncResolveConnectHelper {
private static void checkPort(int port) {
if (port < 0 || port > 65535) {
throw new IllegalArgumentException("Invalid port " + port);
}
}
public static io.netty.util.concurrent.Future<Channel> doBind(VertxInternal vertx,
SocketAddress socketAddress,
ServerBootstrap bootstrap) {
Promise<Channel> promise = vertx.getAcceptorEventLoopGroup().next().newPromise();
try {
bootstrap.channelFactory(vertx.transport().serverChannelFactory(socketAddress.path() != null));
bootstrap.channelFactory(vertx.transport().serverChannelFactory(socketAddress.isDomainSocket()));
} catch (Exception e) {
promise.setFailure(e);
return promise;
}
if (socketAddress.path() != null) {
java.net.SocketAddress converted = vertx.transport().convert(socketAddress, true);
if (socketAddress.isDomainSocket()) {
java.net.SocketAddress converted = vertx.transport().convert(socketAddress);
ChannelFuture future = bootstrap.bind(converted);
future.addListener(f -> {
if (f.isSuccess()) {
@@ -52,8 +50,8 @@ public class AsyncResolveConnectHelper {
}
});
} else {
checkPort(socketAddress.port());
vertx.resolveAddress(socketAddress.host(), res -> {
SocketAddressImpl impl = (SocketAddressImpl) socketAddress;
Handler<AsyncResult<InetAddress>> cont = res -> {
if (res.succeeded()) {
// At this point the name is an IP address so there will be no resolve hit
InetSocketAddress t = new InetSocketAddress(res.result(), socketAddress.port());
@@ -68,7 +66,12 @@ public class AsyncResolveConnectHelper {
} else {
promise.setFailure(res.cause());
}
});
};
if (impl.ipAddress() != null) {
cont.handle(Future.succeededFuture(impl.ipAddress()));
} else {
vertx.resolveAddress(socketAddress.host(), cont);
}
}
return promise;
}

View File

@@ -78,7 +78,7 @@ public final class ChannelProvider {
private void connect(SocketAddress remoteAddress, SocketAddress peerAddress, String serverName, boolean ssl, Promise<Channel> p) {
try {
bootstrap.channelFactory(context.owner().transport().channelFactory(remoteAddress.path() != null));
bootstrap.channelFactory(context.owner().transport().channelFactory(remoteAddress.isDomainSocket()));
} catch (Exception e) {
p.setFailure(e);
return;
@@ -133,7 +133,7 @@ public final class ChannelProvider {
initSSL(peerAddress, serverName, ssl, ch, channelHandler);
}
});
ChannelFuture fut = bootstrap.connect(vertx.transport().convert(remoteAddress, false));
ChannelFuture fut = bootstrap.connect(vertx.transport().convert(remoteAddress));
fut.addListener(res -> {
if (res.isSuccess()) {
connected(fut.channel(), ssl, channelHandler);
@@ -193,7 +193,7 @@ public final class ChannelProvider {
}
bootstrap.resolver(NoopAddressResolverGroup.INSTANCE);
java.net.SocketAddress targetAddress = vertx.transport().convert(remoteAddress, false);
java.net.SocketAddress targetAddress = vertx.transport().convert(remoteAddress);
bootstrap.handler(new ChannelInitializer<Channel>() {
@Override

View File

@@ -198,7 +198,7 @@ public class NetClientImpl implements MetricsProvider, NetClient {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(context.nettyEventLoop());
applyConnectionOptions(remoteAddress.path() != null, bootstrap);
applyConnectionOptions(remoteAddress.isDomainSocket(), bootstrap);
ChannelProvider channelProvider = new ChannelProvider(bootstrap, sslHelper, context, options.getProxyOptions());

View File

@@ -201,7 +201,7 @@ public class NetServerImpl implements Closeable, MetricsProvider, NetServer {
Map<ServerID, NetServerImpl> sharedNetServers = vertx.sharedNetServers();
synchronized (sharedNetServers) {
this.actualPort = localAddress.port(); // Will be updated on bind for a wildcard port
String hostOrPath = localAddress.host() != null ? localAddress.host() : localAddress.path();
String hostOrPath = localAddress.isInetSocket() ? localAddress.host() : localAddress.path();
id = new ServerID(actualPort, hostOrPath);
NetServerImpl shared = sharedNetServers.get(id);
if (shared == null || actualPort == 0) { // Wildcard port will imply a new actual server each time
@@ -250,7 +250,7 @@ public class NetServerImpl implements Closeable, MetricsProvider, NetServer {
}
});
applyConnectionOptions(localAddress.path() != null, bootstrap);
applyConnectionOptions(localAddress.isDomainSocket(), bootstrap);
handlerManager.addHandler(new Handlers(this, handler, exceptionHandler), listenContext);
@@ -271,7 +271,7 @@ public class NetServerImpl implements Closeable, MetricsProvider, NetServer {
}
VertxMetrics metrics = vertx.metricsSPI();
if (metrics != null) {
this.metrics = metrics.createNetServerMetrics(options, new SocketAddressImpl(id.port, id.host));
this.metrics = metrics.createNetServerMetrics(options, SocketAddress.inetSocketAddress(id.port, id.host));
}
} else {
synchronized (sharedNetServers) {
@@ -293,7 +293,7 @@ public class NetServerImpl implements Closeable, MetricsProvider, NetServer {
actualServer = shared;
this.actualPort = shared.actualPort();
VertxMetrics metrics = vertx.metricsSPI();
this.metrics = metrics != null ? metrics.createNetServerMetrics(options, new SocketAddressImpl(id.port, id.host)) : null;
this.metrics = metrics != null ? metrics.createNetServerMetrics(options, SocketAddress.inetSocketAddress(id.port, id.host)) : null;
actualServer.handlerManager.addHandler(new Handlers(this, handler, exceptionHandler), listenContext);
}

View File

@@ -513,7 +513,7 @@ public class SSLHelper {
public SSLEngine createEngine(VertxInternal vertx, SocketAddress socketAddress, String serverName) {
SslContext context = getContext(vertx, null);
SSLEngine engine;
if (socketAddress.path() != null) {
if (socketAddress.isDomainSocket()) {
engine = context.newEngine(ByteBufAllocator.DEFAULT);
} else {
engine = context.newEngine(ByteBufAllocator.DEFAULT, socketAddress.host(), socketAddress.port());

View File

@@ -11,10 +11,15 @@
package io.vertx.core.net.impl;
import io.netty.util.NetUtil;
import io.vertx.core.VertxException;
import io.vertx.core.impl.Arguments;
import io.vertx.core.net.SocketAddress;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Objects;
/**
@@ -22,22 +27,64 @@ import java.util.Objects;
*/
public class SocketAddressImpl implements SocketAddress{
private final String hostAddress;
private final String host;
private final String hostName;
private final InetAddress ipAddress;
private final int port;
private final String path;
public SocketAddressImpl(int port, String host) {
Objects.requireNonNull(host, "no null host accepted");
Arguments.require(!host.isEmpty(), "no empty host accepted");
Arguments.requireInRange(port, 0, 65535, "port p must be in range 0 <= p <= 65535");
this.port = port;
this.hostAddress = host;
public SocketAddressImpl(InetSocketAddress address) {
Arguments.requireInRange(address.getPort(), 0, 65535, "port p must be in range 0 <= p <= 65535");
this.path = null;
this.port= address.getPort();
this.host = address.getHostString();
if (address.isUnresolved()) {
this.hostName = address.getHostName();
this.ipAddress = null;
} else {
String host = address.getHostString();
if (NetUtil.isValidIpV4Address(host) || NetUtil.isValidIpV6Address(host)) {
host = null;
}
this.hostName = host;
this.ipAddress = address.getAddress();
}
}
public SocketAddressImpl(int port, String host) {
Arguments.requireInRange(port, 0, 65535, "port p must be in range 0 <= p <= 65535");
this.path = null;
this.port = port;
if (NetUtil.isValidIpV4Address(host)) {
InetAddress ip;
try {
ip = InetAddress.getByAddress(NetUtil.createByteArrayFromIpAddressString(host));
} catch (UnknownHostException e) {
throw new VertxException(e);
}
this.host = host;
this.hostName = null;
this.ipAddress = ip;
} else if (NetUtil.isValidIpV6Address(host)) {
Inet6Address ip = NetUtil.getByName(host);
this.host = host;
this.hostName = null;
this.ipAddress = ip;
} else {
Arguments.require(!host.isEmpty(), "host name must not be empty");
this.host = host;
this.hostName = host;
this.ipAddress = null;
}
}
public SocketAddressImpl(String path) {
Objects.requireNonNull(path, "domain socket path must be non null");
Arguments.require(!path.isEmpty(), "domain socket must not be empty");
this.port = -1;
this.hostAddress = null;
this.host = null;
this.ipAddress = null;
this.hostName = null;
this.path = path;
}
@@ -47,21 +94,45 @@ public class SocketAddressImpl implements SocketAddress{
}
public String host() {
return hostAddress;
return host;
}
@Override
public String hostName() {
return hostName;
}
@Override
public String hostAddress() {
return ipAddress == null ? null : ipAddress.getHostAddress();
}
public int port() {
return port;
}
@Override
public boolean isInetSocket() {
return path == null;
}
@Override
public boolean isDomainSocket() {
return path != null;
}
public String toString() {
if (path == null) {
return hostAddress + ":" + port;
return host + ":" + port;
} else {
return path;
}
}
public InetAddress ipAddress() {
return ipAddress;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -70,7 +141,7 @@ public class SocketAddressImpl implements SocketAddress{
SocketAddressImpl that = (SocketAddressImpl) o;
if (port != that.port) return false;
if (hostAddress != null ? !hostAddress.equals(that.hostAddress) : that.hostAddress != null) return false;
if (host != null ? !host.equals(that.host) : that.host != null) return false;
if (path != null ? !path.equals(that.path) : that.path != null) return false;
return true;
@@ -78,7 +149,7 @@ public class SocketAddressImpl implements SocketAddress{
@Override
public int hashCode() {
int result = hostAddress != null ? hostAddress.hashCode() : 0;
int result = host != null ? host.hashCode() : 0;
result = 31 * result + (path != null ? path.hashCode() : 0);
result = 31 * result + port;
return result;

View File

@@ -66,15 +66,11 @@ class EpollTransport extends Transport {
}
@Override
public SocketAddress convert(io.vertx.core.net.SocketAddress address, boolean resolved) {
if (address.path() != null) {
public SocketAddress convert(io.vertx.core.net.SocketAddress address) {
if (address.isDomainSocket()) {
return new DomainSocketAddress(address.path());
} else {
if (resolved) {
return new InetSocketAddress(address.host(), address.port());
} else {
return InetSocketAddress.createUnresolved(address.host(), address.port());
}
return super.convert(address);
}
}

View File

@@ -37,15 +37,11 @@ class KQueueTransport extends Transport {
}
@Override
public SocketAddress convert(io.vertx.core.net.SocketAddress address, boolean resolved) {
if (address.path() != null) {
public SocketAddress convert(io.vertx.core.net.SocketAddress address) {
if (address.isDomainSocket()) {
return new DomainSocketAddress(address.path());
} else {
if (resolved) {
return new InetSocketAddress(address.host(), address.port());
} else {
return InetSocketAddress.createUnresolved(address.host(), address.port());
}
return super.convert(address);
}
}

View File

@@ -26,6 +26,7 @@ import io.vertx.core.net.NetServerOptions;
import io.vertx.core.net.impl.PartialPooledByteBufAllocator;
import io.vertx.core.net.impl.SocketAddressImpl;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
@@ -106,12 +107,13 @@ public class Transport {
return null;
}
public SocketAddress convert(io.vertx.core.net.SocketAddress address, boolean resolved) {
if (address.path() != null) {
public SocketAddress convert(io.vertx.core.net.SocketAddress address) {
if (address.isDomainSocket()) {
throw new IllegalArgumentException("Domain socket not supported by JDK transport");
} else {
if (resolved) {
return new InetSocketAddress(address.host(), address.port());
InetAddress ip = ((SocketAddressImpl) address).ipAddress();
if (ip != null) {
return new InetSocketAddress(ip, address.port());
} else {
return InetSocketAddress.createUnresolved(address.host(), address.port());
}
@@ -120,12 +122,7 @@ public class Transport {
public io.vertx.core.net.SocketAddress convert(SocketAddress address) {
if (address instanceof InetSocketAddress) {
InetSocketAddress inetSocketAddress = (InetSocketAddress) address;
if (inetSocketAddress.isUnresolved()) {
return new SocketAddressImpl(inetSocketAddress.getPort(), inetSocketAddress.getHostName());
} else {
return new SocketAddressImpl(inetSocketAddress.getPort(), inetSocketAddress.getAddress().getHostAddress());
}
return io.vertx.core.net.SocketAddress.inetSocketAddress((InetSocketAddress) address);
} else {
return null;
}

View File

@@ -1006,7 +1006,7 @@ public class Http1xTest extends HttpTest {
@Test
public void testTimedOutWaiterDoesntConnect() throws Exception {
Assume.assumeTrue("Domain socket don't pass this test", testAddress.path() == null);
Assume.assumeTrue("Domain socket don't pass this test", testAddress.isInetSocket());
long responseDelay = 300;
int requests = 6;
client.close();
@@ -2823,7 +2823,7 @@ public class Http1xTest extends HttpTest {
Handler<NetSocket> connectHandler
) throws Exception {
// Cannot reliably pass due to https://github.com/netty/netty/issues/9113
Assume.assumeTrue(testAddress.path() == null);
Assume.assumeTrue(testAddress.isInetSocket());
client.close();
server.close();

View File

@@ -2593,7 +2593,7 @@ public abstract class HttpTest extends HttpTestBase {
@Test
public void testRemoteAddress() {
server.requestHandler(req -> {
if (testAddress.host() != null) {
if (testAddress.isInetSocket()) {
assertEquals("127.0.0.1", req.remoteAddress().host());
} else {
// Returns null for domain sockets

View File

@@ -738,14 +738,6 @@ public class NetTest extends VertxTestBase {
assertTrue(options.getKeyCertOptions() instanceof PemKeyCertOptions);
}
@Test
public void testSocketAddress() throws Exception {
assertNullPointerException(() -> new SocketAddressImpl(0, null));
assertIllegalArgumentException(() -> new SocketAddressImpl(0, ""));
assertIllegalArgumentException(() -> new SocketAddressImpl(-1, "someHost"));
assertIllegalArgumentException(() -> new SocketAddressImpl(65536, "someHost"));
}
@Test
public void testWriteHandlerSuccess() throws Exception {
CompletableFuture<Void> close = new CompletableFuture<>();
@@ -1737,7 +1729,7 @@ public class NetTest extends VertxTestBase {
// To get this to reliably pass with a lot of connections.
public void testSharedServersRoundRobin() throws Exception {
boolean domainSocket = testAddress.path() != null;
boolean domainSocket = testAddress.isDomainSocket();
int numServers = VertxOptions.DEFAULT_EVENT_LOOP_POOL_SIZE / 2- 1;
int numConnections = numServers * (domainSocket ? 10 : 20);
@@ -1896,12 +1888,16 @@ public class NetTest extends VertxTestBase {
server.connectHandler(socket -> {
SocketAddress addr = socket.remoteAddress();
assertEquals("127.0.0.1", addr.host());
assertEquals(null, addr.hostName());
assertEquals("127.0.0.1", addr.hostAddress());
socket.close();
}).listen(1234, "localhost", ar -> {
assertTrue(ar.succeeded());
vertx.createNetClient(new NetClientOptions()).connect(1234, "localhost", onSuccess(socket -> {
SocketAddress addr = socket.remoteAddress();
assertEquals("127.0.0.1", addr.host());
assertEquals("localhost", addr.host());
assertEquals("localhost", addr.hostName());
assertEquals("127.0.0.1", addr.hostAddress());
assertEquals(addr.port(), 1234);
socket.closeHandler(v -> testComplete());
}));

View File

@@ -0,0 +1,115 @@
package io.vertx.core.net;
import io.netty.util.NetUtil;
import io.vertx.test.core.VertxTestBase;
import org.junit.Test;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import static io.vertx.test.core.TestUtils.assertIllegalArgumentException;
import static io.vertx.test.core.TestUtils.assertNullPointerException;
public class SocketAddressTest extends VertxTestBase {
@Test
public void testInetSocketAddressFromUnresolvedAddress() {
SocketAddress addr = SocketAddress.inetSocketAddress(InetSocketAddress.createUnresolved("localhost", 8080));
assertEquals("localhost", addr.host());
assertEquals("localhost", addr.hostName());
assertEquals(null, addr.hostAddress());
assertEquals(8080, addr.port());
assertFalse(addr.isDomainSocket());
assertTrue(addr.isInetSocket());
}
@Test
public void testInetSocketAddressFromResolvedAddress() {
InetSocketAddress expected = new InetSocketAddress("localhost", 8080);
SocketAddress addr = SocketAddress.inetSocketAddress(expected);
assertEquals("localhost", addr.host());
assertEquals("localhost", addr.hostName());
assertEquals(expected.getAddress().getHostAddress(), addr.hostAddress());
assertEquals(8080, addr.port());
assertFalse(addr.isDomainSocket());
assertTrue(addr.isInetSocket());
}
@Test
public void testInetSocketAddressIpV4Address() throws Exception {
InetAddress ip = InetAddress.getByAddress(new byte[]{127, 0, 0, 1});
SocketAddress addr = SocketAddress.inetSocketAddress(new InetSocketAddress(ip, 8080));
assertEquals("127.0.0.1", addr.host());
assertNull(addr.hostName());
assertEquals(ip.getHostAddress(), addr.hostAddress());
assertEquals(8080, addr.port());
assertFalse(addr.isDomainSocket());
assertTrue(addr.isInetSocket());
}
@Test
public void testInetSocketAddressIpV6Address() {
InetAddress ip = NetUtil.getByName("::1");
SocketAddress addr = SocketAddress.inetSocketAddress(new InetSocketAddress(ip, 8080));
assertEquals("0:0:0:0:0:0:0:1", addr.host());
assertNull(addr.hostName());
assertEquals(ip.getHostAddress(), addr.hostAddress());
assertEquals(8080, addr.port());
assertFalse(addr.isDomainSocket());
assertTrue(addr.isInetSocket());
}
@Test
public void testInetSocketAddressFromHostName() {
SocketAddress addr = SocketAddress.inetSocketAddress(8080, "localhost");
assertEquals("localhost", addr.host());
assertEquals("localhost", addr.hostName());
assertNull(addr.hostAddress());
assertEquals(8080, addr.port());
assertFalse(addr.isDomainSocket());
assertTrue(addr.isInetSocket());
}
@Test
public void testInetSocketAddressFromIpV4AddressHost() {
SocketAddress addr = SocketAddress.inetSocketAddress(8080, "127.0.0.1");
assertEquals("127.0.0.1", addr.host());
assertEquals(null, addr.hostName());
assertEquals("127.0.0.1", addr.hostAddress());
assertEquals(8080, addr.port());
assertFalse(addr.isDomainSocket());
assertTrue(addr.isInetSocket());
}
@Test
public void testInetSocketAddressFromIpV6AddressHost() {
SocketAddress addr = SocketAddress.inetSocketAddress(8080, "::1");
assertEquals("::1", addr.host());
assertEquals(null, addr.hostName());
assertEquals("0:0:0:0:0:0:0:1", addr.hostAddress());
assertEquals(8080, addr.port());
assertFalse(addr.isDomainSocket());
assertTrue(addr.isInetSocket());
}
@Test
public void testDomainSocketAddress() {
SocketAddress addr = SocketAddress.domainSocketAddress("/foo");
assertEquals("/foo", addr.path());
assertNull(addr.host());
assertNull(addr.hostAddress());
assertNull(addr.hostName());
assertEquals(-1, addr.port());
assertTrue(addr.isDomainSocket());
assertFalse(addr.isInetSocket());
}
@Test
public void testSocketAddress() throws Exception {
assertNullPointerException(() -> SocketAddress.domainSocketAddress(null));
assertNullPointerException(() -> SocketAddress.inetSocketAddress(0, null));
assertIllegalArgumentException(() -> SocketAddress.inetSocketAddress(0, ""));
assertIllegalArgumentException(() -> SocketAddress.inetSocketAddress(-1, "someHost"));
assertIllegalArgumentException(() -> SocketAddress.inetSocketAddress(65536, "someHost"));
}
}