Skip to content

Commit 8d3e73b

Browse files
mariaralDaveCTurner
authored andcommitted
Add host address to BindTransportException message (#51269)
When bind fails, show the host address in addition to the port. This helps debugging cases with wrong "network.host" values. Closes #48001
1 parent 337153b commit 8d3e73b

File tree

8 files changed

+108
-14
lines changed

8 files changed

+108
-14
lines changed

buildSrc/src/main/resources/forbidden/jdk-signatures.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ java.net.MulticastSocket#<init>(int)
5959
java.net.ServerSocket#<init>(int)
6060
java.net.ServerSocket#<init>(int,int)
6161

62-
@defaultMessage use NetworkAddress format/formatAddress to print IP or IP+ports
62+
@defaultMessage use NetworkAddress format() to print IP or IP+ports
6363
java.net.InetAddress#toString()
6464
java.net.InetAddress#getHostAddress()
6565
java.net.Inet4Address#getHostAddress()

modules/transport-netty4/src/test/java/org/elasticsearch/http/netty4/Netty4HttpServerTransportTests.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import io.netty.handler.codec.http.HttpVersion;
4242
import org.elasticsearch.ElasticsearchException;
4343
import org.elasticsearch.common.bytes.BytesArray;
44+
import org.elasticsearch.common.network.NetworkAddress;
4445
import org.elasticsearch.common.network.NetworkService;
4546
import org.elasticsearch.common.settings.Setting;
4647
import org.elasticsearch.common.settings.Settings;
@@ -195,11 +196,17 @@ public void testBindUnavailableAddress() {
195196
xContentRegistry(), new NullDispatcher())) {
196197
transport.start();
197198
TransportAddress remoteAddress = randomFrom(transport.boundAddress().boundAddresses());
198-
Settings settings = Settings.builder().put("http.port", remoteAddress.getPort()).build();
199+
Settings settings = Settings.builder()
200+
.put("http.port", remoteAddress.getPort())
201+
.put("network.host", remoteAddress.getAddress())
202+
.build();
199203
try (Netty4HttpServerTransport otherTransport = new Netty4HttpServerTransport(settings, networkService, bigArrays, threadPool,
200204
xContentRegistry(), new NullDispatcher())) {
201205
BindHttpException bindHttpException = expectThrows(BindHttpException.class, otherTransport::start);
202-
assertEquals("Failed to bind to [" + remoteAddress.getPort() + "]", bindHttpException.getMessage());
206+
assertEquals(
207+
"Failed to bind to " + NetworkAddress.format(remoteAddress.address()),
208+
bindHttpException.getMessage()
209+
);
203210
}
204211
}
205212
}

plugins/transport-nio/src/test/java/org/elasticsearch/http/nio/NioHttpServerTransportTests.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import io.netty.handler.codec.http.HttpVersion;
3434
import org.elasticsearch.ElasticsearchException;
3535
import org.elasticsearch.common.bytes.BytesArray;
36+
import org.elasticsearch.common.network.NetworkAddress;
3637
import org.elasticsearch.common.network.NetworkService;
3738
import org.elasticsearch.common.settings.Setting;
3839
import org.elasticsearch.common.settings.Settings;
@@ -190,11 +191,17 @@ public void testBindUnavailableAddress() {
190191
threadPool, xContentRegistry(), new NullDispatcher(), new NioGroupFactory(Settings.EMPTY, logger))) {
191192
transport.start();
192193
TransportAddress remoteAddress = randomFrom(transport.boundAddress().boundAddresses());
193-
Settings settings = Settings.builder().put("http.port", remoteAddress.getPort()).build();
194+
Settings settings = Settings.builder()
195+
.put("http.port", remoteAddress.getPort())
196+
.put("network.host", remoteAddress.getAddress())
197+
.build();
194198
try (NioHttpServerTransport otherTransport = new NioHttpServerTransport(settings, networkService, bigArrays, pageRecycler,
195199
threadPool, xContentRegistry(), new NullDispatcher(), new NioGroupFactory(Settings.EMPTY, logger))) {
196200
BindHttpException bindHttpException = expectThrows(BindHttpException.class, () -> otherTransport.start());
197-
assertEquals("Failed to bind to [" + remoteAddress.getPort() + "]", bindHttpException.getMessage());
201+
assertEquals(
202+
"Failed to bind to " + NetworkAddress.format(remoteAddress.address()),
203+
bindHttpException.getMessage()
204+
);
198205
}
199206
}
200207
}

server/src/main/java/org/elasticsearch/common/network/NetworkAddress.java

+51-6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
package org.elasticsearch.common.network;
2121

22+
import org.elasticsearch.common.transport.PortsRange;
23+
2224
import java.net.Inet6Address;
2325
import java.net.InetAddress;
2426
import java.net.InetSocketAddress;
@@ -66,7 +68,7 @@ private NetworkAddress() {}
6668
* @return formatted string
6769
*/
6870
public static String format(InetAddress address) {
69-
return format(address, -1);
71+
return format(address, new PortsRange(""));
7072
}
7173

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

91-
// note, we don't validate port, because we only allow InetSocketAddress
92-
static String format(InetAddress address, int port) {
93+
/**
94+
* Formats a network address and port for display purposes.
95+
* <p>
96+
* This formats the address with {@link #format(InetAddress)}
97+
* and appends the port number. IPv6 addresses will be bracketed.
98+
* Any host information, if present is ignored.
99+
* <p>
100+
* Example output:
101+
* <ul>
102+
* <li>IPv4: {@code 127.0.0.1:9300}</li>
103+
* <li>IPv6: {@code [::1]:9300}</li>
104+
* </ul>
105+
* @param address IPv4 or IPv6 address
106+
* @param port port
107+
* @return formatted string
108+
*/
109+
public static String format(InetAddress address, int port) {
110+
return format(address, new PortsRange(String.valueOf(port)));
111+
}
112+
113+
/**
114+
* Formats a network address and port range for display purposes.
115+
* <p>
116+
* This formats the address with {@link #format(InetAddress)}
117+
* and appends the port range in brackets. In case there is only one
118+
* port, the result is the same with {@link #format(InetAddress, int)}.
119+
* <p>
120+
* Example output:
121+
* <ul>
122+
* <li>IPv4 no port: {@code 127.0.0.1}</li>
123+
* <li>IPv4 single port: {@code 127.0.0.1:9300}</li>
124+
* <li>IPv4 multiple ports: {@code 127.0.0.1:[9300-9400]}</li>
125+
* <li>IPv6 multiple ports: {@code [::1]:[9300-9400]}</li>
126+
* </ul>
127+
* @param address IPv4 or IPv6 address
128+
* @param portsRange range of ports
129+
* @return formatted string
130+
*/
131+
public static String format(InetAddress address, PortsRange portsRange) {
93132
Objects.requireNonNull(address);
94133

95134
StringBuilder builder = new StringBuilder();
96135

97-
if (port != -1 && address instanceof Inet6Address) {
136+
int numberOfPorts = portsRange.ports().length;
137+
138+
if (numberOfPorts != 0 && address instanceof Inet6Address) {
98139
builder.append(InetAddresses.toUriString(address));
99140
} else {
100141
builder.append(InetAddresses.toAddrString(address));
101142
}
102143

103-
if (port != -1) {
144+
if (numberOfPorts != 0) {
104145
builder.append(':');
105-
builder.append(port);
146+
if (numberOfPorts == 1) {
147+
builder.append(portsRange.getPortRangeString());
148+
} else {
149+
builder.append("[").append(portsRange.getPortRangeString()).append("]");
150+
}
106151
}
107152

108153
return builder.toString();

server/src/main/java/org/elasticsearch/http/AbstractHttpServerTransport.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,10 @@ private TransportAddress bindAddress(final InetAddress hostAddress) {
174174
return true;
175175
});
176176
if (!success) {
177-
throw new BindHttpException("Failed to bind to [" + port.getPortRangeString() + "]", lastException.get());
177+
throw new BindHttpException(
178+
"Failed to bind to " + NetworkAddress.format(hostAddress, port),
179+
lastException.get()
180+
);
178181
}
179182

180183
if (logger.isDebugEnabled()) {

server/src/main/java/org/elasticsearch/transport/TcpTransport.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,10 @@ private InetSocketAddress bindToPort(final String name, final InetAddress hostAd
387387
return true;
388388
});
389389
if (!success) {
390-
throw new BindTransportException("Failed to bind to [" + port + "]", lastException.get());
390+
throw new BindTransportException(
391+
"Failed to bind to " + NetworkAddress.format(hostAddress, portsRange),
392+
lastException.get()
393+
);
391394
}
392395
} finally {
393396
closeLock.writeLock().unlock();

server/src/test/java/org/elasticsearch/common/network/NetworkAddressTests.java

+25
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.common.network;
2121

22+
import org.elasticsearch.common.transport.PortsRange;
2223
import org.elasticsearch.test.ESTestCase;
2324

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

56+
public void testFormatPortsRangeV4() throws Exception {
57+
assertEquals("127.0.0.1", NetworkAddress.format(forge("localhost", "127.0.0.1"), new PortsRange("")));
58+
assertEquals("127.0.0.1", NetworkAddress.format(forge(null, "127.0.0.1"), new PortsRange("")));
59+
60+
assertEquals("127.0.0.1:9300", NetworkAddress.format(forge("localhost", "127.0.0.1"), new PortsRange("9300")));
61+
assertEquals("127.0.0.1:9300", NetworkAddress.format(forge(null, "127.0.0.1"), new PortsRange("9300")));
62+
63+
assertEquals("127.0.0.1:[9300-9400]", NetworkAddress.format(forge("localhost", "127.0.0.1"), new PortsRange("9300-9400")));
64+
assertEquals("127.0.0.1:[9300-9400]", NetworkAddress.format(forge(null, "127.0.0.1"), new PortsRange("9300-9400")));
65+
}
66+
67+
public void testFormatPortsRangeV6() throws Exception {
68+
assertEquals("::1", NetworkAddress.format(forge("localhost", "::1"), new PortsRange("")));
69+
assertEquals("::1", NetworkAddress.format(forge(null, "::1"), new PortsRange("")));
70+
71+
assertEquals("[::1]:9300", NetworkAddress.format(forge("localhost", "::1"), new PortsRange("9300")));
72+
assertEquals("[::1]:9300", NetworkAddress.format(forge(null, "::1"), new PortsRange("9300")));
73+
74+
assertEquals("[::1]:[9300-9400]", NetworkAddress.format(forge("localhost", "::1"), new PortsRange("9300-9400")));
75+
assertEquals("[::1]:[9300-9400]", NetworkAddress.format(forge(null, "::1"), new PortsRange("9300-9400")));
76+
}
77+
5578
public void testNoScopeID() throws Exception {
5679
assertEquals("::1", NetworkAddress.format(forgeScoped(null, "::1", 5)));
5780
assertEquals("::1", NetworkAddress.format(forgeScoped("localhost", "::1", 5)));
81+
assertEquals("::1", NetworkAddress.format(forgeScoped("localhost", "::1", 5), new PortsRange("")));
5882

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

6388
/** Test that ipv4 address formatting round trips */

test/framework/src/main/java/org/elasticsearch/transport/AbstractSimpleTransportTestCase.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.elasticsearch.common.io.stream.StreamOutput;
3939
import org.elasticsearch.common.logging.Loggers;
4040
import org.elasticsearch.common.network.CloseableChannel;
41+
import org.elasticsearch.common.network.NetworkAddress;
4142
import org.elasticsearch.common.network.NetworkUtils;
4243
import org.elasticsearch.common.settings.ClusterSettings;
4344
import org.elasticsearch.common.settings.Setting;
@@ -2701,13 +2702,16 @@ public void testProfilesIncludesDefault() {
27012702

27022703
public void testBindUnavailableAddress() {
27032704
int port = serviceA.boundAddress().publishAddress().getPort();
2705+
String address = serviceA.boundAddress().publishAddress().getAddress();
27042706
Settings settings = Settings.builder()
27052707
.put(Node.NODE_NAME_SETTING.getKey(), "foobar")
2708+
.put(TransportSettings.HOST.getKey(), address)
27062709
.put(TransportSettings.PORT.getKey(), port)
27072710
.build();
27082711
BindTransportException bindTransportException = expectThrows(BindTransportException.class,
27092712
() -> buildService("test", Version.CURRENT, settings));
2710-
assertEquals("Failed to bind to ["+ port + "]", bindTransportException.getMessage());
2713+
InetSocketAddress inetSocketAddress = serviceA.boundAddress().publishAddress().address();
2714+
assertEquals("Failed to bind to " + NetworkAddress.format(inetSocketAddress), bindTransportException.getMessage());
27112715
}
27122716

27132717
public void testChannelCloseWhileConnecting() {

0 commit comments

Comments
 (0)