Skip to content

Commit

Permalink
Add host address to BindTransportException message (#51269)
Browse files Browse the repository at this point in the history
When bind fails, show the host address in addition to the port. This
helps debugging cases with wrong "network.host" values.

Closes #48001
  • Loading branch information
mariaral authored Feb 4, 2020
1 parent fef0e1d commit 84dd9dc
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 14 deletions.
2 changes: 1 addition & 1 deletion buildSrc/src/main/resources/forbidden/jdk-signatures.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ java.net.MulticastSocket#<init>(int)
java.net.ServerSocket#<init>(int)
java.net.ServerSocket#<init>(int,int)

@defaultMessage use NetworkAddress format/formatAddress to print IP or IP+ports
@defaultMessage use NetworkAddress format() to print IP or IP+ports
java.net.InetAddress#toString()
java.net.InetAddress#getHostAddress()
java.net.Inet4Address#getHostAddress()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import io.netty.handler.codec.http.HttpVersion;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.network.NetworkAddress;
import org.elasticsearch.common.network.NetworkService;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
Expand Down Expand Up @@ -195,11 +196,17 @@ public void testBindUnavailableAddress() {
xContentRegistry(), new NullDispatcher())) {
transport.start();
TransportAddress remoteAddress = randomFrom(transport.boundAddress().boundAddresses());
Settings settings = Settings.builder().put("http.port", remoteAddress.getPort()).build();
Settings settings = Settings.builder()
.put("http.port", remoteAddress.getPort())
.put("network.host", remoteAddress.getAddress())
.build();
try (Netty4HttpServerTransport otherTransport = new Netty4HttpServerTransport(settings, networkService, bigArrays, threadPool,
xContentRegistry(), new NullDispatcher())) {
BindHttpException bindHttpException = expectThrows(BindHttpException.class, otherTransport::start);
assertEquals("Failed to bind to [" + remoteAddress.getPort() + "]", bindHttpException.getMessage());
assertEquals(
"Failed to bind to " + NetworkAddress.format(remoteAddress.address()),
bindHttpException.getMessage()
);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import io.netty.handler.codec.http.HttpVersion;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.network.NetworkAddress;
import org.elasticsearch.common.network.NetworkService;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
Expand Down Expand Up @@ -190,11 +191,17 @@ public void testBindUnavailableAddress() {
threadPool, xContentRegistry(), new NullDispatcher(), new NioGroupFactory(Settings.EMPTY, logger))) {
transport.start();
TransportAddress remoteAddress = randomFrom(transport.boundAddress().boundAddresses());
Settings settings = Settings.builder().put("http.port", remoteAddress.getPort()).build();
Settings settings = Settings.builder()
.put("http.port", remoteAddress.getPort())
.put("network.host", remoteAddress.getAddress())
.build();
try (NioHttpServerTransport otherTransport = new NioHttpServerTransport(settings, networkService, bigArrays, pageRecycler,
threadPool, xContentRegistry(), new NullDispatcher(), new NioGroupFactory(Settings.EMPTY, logger))) {
BindHttpException bindHttpException = expectThrows(BindHttpException.class, () -> otherTransport.start());
assertEquals("Failed to bind to [" + remoteAddress.getPort() + "]", bindHttpException.getMessage());
assertEquals(
"Failed to bind to " + NetworkAddress.format(remoteAddress.address()),
bindHttpException.getMessage()
);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

package org.elasticsearch.common.network;

import org.elasticsearch.common.transport.PortsRange;

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
Expand Down Expand Up @@ -66,7 +68,7 @@ private NetworkAddress() {}
* @return formatted string
*/
public static String format(InetAddress address) {
return format(address, -1);
return format(address, new PortsRange(""));
}

/**
Expand All @@ -88,21 +90,64 @@ public static String format(InetSocketAddress address) {
return format(address.getAddress(), address.getPort());
}

// note, we don't validate port, because we only allow InetSocketAddress
static String format(InetAddress address, int port) {
/**
* Formats a network address and port for display purposes.
* <p>
* This formats the address with {@link #format(InetAddress)}
* and appends the port number. IPv6 addresses will be bracketed.
* Any host information, if present is ignored.
* <p>
* Example output:
* <ul>
* <li>IPv4: {@code 127.0.0.1:9300}</li>
* <li>IPv6: {@code [::1]:9300}</li>
* </ul>
* @param address IPv4 or IPv6 address
* @param port port
* @return formatted string
*/
public static String format(InetAddress address, int port) {
return format(address, new PortsRange(String.valueOf(port)));
}

/**
* Formats a network address and port range for display purposes.
* <p>
* This formats the address with {@link #format(InetAddress)}
* and appends the port range in brackets. In case there is only one
* port, the result is the same with {@link #format(InetAddress, int)}.
* <p>
* Example output:
* <ul>
* <li>IPv4 no port: {@code 127.0.0.1}</li>
* <li>IPv4 single port: {@code 127.0.0.1:9300}</li>
* <li>IPv4 multiple ports: {@code 127.0.0.1:[9300-9400]}</li>
* <li>IPv6 multiple ports: {@code [::1]:[9300-9400]}</li>
* </ul>
* @param address IPv4 or IPv6 address
* @param portsRange range of ports
* @return formatted string
*/
public static String format(InetAddress address, PortsRange portsRange) {
Objects.requireNonNull(address);

StringBuilder builder = new StringBuilder();

if (port != -1 && address instanceof Inet6Address) {
int numberOfPorts = portsRange.ports().length;

if (numberOfPorts != 0 && address instanceof Inet6Address) {
builder.append(InetAddresses.toUriString(address));
} else {
builder.append(InetAddresses.toAddrString(address));
}

if (port != -1) {
if (numberOfPorts != 0) {
builder.append(':');
builder.append(port);
if (numberOfPorts == 1) {
builder.append(portsRange.getPortRangeString());
} else {
builder.append("[").append(portsRange.getPortRangeString()).append("]");
}
}

return builder.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,10 @@ private TransportAddress bindAddress(final InetAddress hostAddress) {
return true;
});
if (!success) {
throw new BindHttpException("Failed to bind to [" + port.getPortRangeString() + "]", lastException.get());
throw new BindHttpException(
"Failed to bind to " + NetworkAddress.format(hostAddress, port),
lastException.get()
);
}

if (logger.isDebugEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,10 @@ private InetSocketAddress bindToPort(final String name, final InetAddress hostAd
return true;
});
if (!success) {
throw new BindTransportException("Failed to bind to [" + port + "]", lastException.get());
throw new BindTransportException(
"Failed to bind to " + NetworkAddress.format(hostAddress, portsRange),
lastException.get()
);
}
} finally {
closeLock.writeLock().unlock();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package org.elasticsearch.common.network;

import org.elasticsearch.common.transport.PortsRange;
import org.elasticsearch.test.ESTestCase;

import java.io.IOException;
Expand Down Expand Up @@ -52,12 +53,36 @@ public void testFormatPortV6() throws Exception {
assertEquals("[::1]:1234", NetworkAddress.format(new InetSocketAddress(forge(null, "::1"), 1234)));
}

public void testFormatPortsRangeV4() throws Exception {
assertEquals("127.0.0.1", NetworkAddress.format(forge("localhost", "127.0.0.1"), new PortsRange("")));
assertEquals("127.0.0.1", NetworkAddress.format(forge(null, "127.0.0.1"), new PortsRange("")));

assertEquals("127.0.0.1:9300", NetworkAddress.format(forge("localhost", "127.0.0.1"), new PortsRange("9300")));
assertEquals("127.0.0.1:9300", NetworkAddress.format(forge(null, "127.0.0.1"), new PortsRange("9300")));

assertEquals("127.0.0.1:[9300-9400]", NetworkAddress.format(forge("localhost", "127.0.0.1"), new PortsRange("9300-9400")));
assertEquals("127.0.0.1:[9300-9400]", NetworkAddress.format(forge(null, "127.0.0.1"), new PortsRange("9300-9400")));
}

public void testFormatPortsRangeV6() throws Exception {
assertEquals("::1", NetworkAddress.format(forge("localhost", "::1"), new PortsRange("")));
assertEquals("::1", NetworkAddress.format(forge(null, "::1"), new PortsRange("")));

assertEquals("[::1]:9300", NetworkAddress.format(forge("localhost", "::1"), new PortsRange("9300")));
assertEquals("[::1]:9300", NetworkAddress.format(forge(null, "::1"), new PortsRange("9300")));

assertEquals("[::1]:[9300-9400]", NetworkAddress.format(forge("localhost", "::1"), new PortsRange("9300-9400")));
assertEquals("[::1]:[9300-9400]", NetworkAddress.format(forge(null, "::1"), new PortsRange("9300-9400")));
}

public void testNoScopeID() throws Exception {
assertEquals("::1", NetworkAddress.format(forgeScoped(null, "::1", 5)));
assertEquals("::1", NetworkAddress.format(forgeScoped("localhost", "::1", 5)));
assertEquals("::1", NetworkAddress.format(forgeScoped("localhost", "::1", 5), new PortsRange("")));

assertEquals("[::1]:1234", NetworkAddress.format(new InetSocketAddress(forgeScoped(null, "::1", 5), 1234)));
assertEquals("[::1]:1234", NetworkAddress.format(new InetSocketAddress(forgeScoped("localhost", "::1", 5), 1234)));
assertEquals("[::1]:[9300-9400]", NetworkAddress.format(forgeScoped("localhost", "::1", 5), new PortsRange("9300-9400")));
}

/** Test that ipv4 address formatting round trips */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.network.CloseableChannel;
import org.elasticsearch.common.network.NetworkAddress;
import org.elasticsearch.common.network.NetworkUtils;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Setting;
Expand Down Expand Up @@ -2698,13 +2699,16 @@ public void testProfilesIncludesDefault() {

public void testBindUnavailableAddress() {
int port = serviceA.boundAddress().publishAddress().getPort();
String address = serviceA.boundAddress().publishAddress().getAddress();
Settings settings = Settings.builder()
.put(Node.NODE_NAME_SETTING.getKey(), "foobar")
.put(TransportSettings.HOST.getKey(), address)
.put(TransportSettings.PORT.getKey(), port)
.build();
BindTransportException bindTransportException = expectThrows(BindTransportException.class,
() -> buildService("test", Version.CURRENT, settings));
assertEquals("Failed to bind to ["+ port + "]", bindTransportException.getMessage());
InetSocketAddress inetSocketAddress = serviceA.boundAddress().publishAddress().address();
assertEquals("Failed to bind to " + NetworkAddress.format(inetSocketAddress), bindTransportException.getMessage());
}

public void testChannelCloseWhileConnecting() {
Expand Down

0 comments on commit 84dd9dc

Please sign in to comment.