Skip to content

Commit c0f0b33

Browse files
authored
HADOOP-17542. IPV6 support in Netutils#createSocketAddress (#3217)
* HADOOP-17542. IPV6 support in Netutils#createSocketAddress * HADOOP-17542. IPV6 support in Netutils#createSocketAddress, review comments
1 parent 7118db5 commit c0f0b33

File tree

3 files changed

+81
-1
lines changed

3 files changed

+81
-1
lines changed

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/Path.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,16 @@ public Path(String pathString) throws IllegalArgumentException {
199199
int start = 0;
200200

201201
// parse uri scheme, if any
202-
int colon = pathString.indexOf(':');
202+
int colon = -1;
203203
int slash = pathString.indexOf('/');
204+
if (StringUtils.countMatches(pathString, ":") > 2) {
205+
//In case of IPv6 address, we should be able to parse the scheme
206+
// correctly (This will ensure to parse path with & without scheme
207+
// correctly in IPv6).
208+
colon = pathString.indexOf(":/");
209+
} else {
210+
colon = pathString.indexOf(':');
211+
}
204212
if ((colon != -1) &&
205213
((slash == -1) || (colon < slash))) { // has a scheme
206214
scheme = pathString.substring(0, colon);

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/NetUtils.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545

4646
import javax.net.SocketFactory;
4747

48+
import org.apache.commons.lang3.StringUtils;
4849
import org.apache.hadoop.security.AccessControlException;
4950
import org.apache.hadoop.thirdparty.com.google.common.cache.Cache;
5051
import org.apache.hadoop.thirdparty.com.google.common.cache.CacheBuilder;
@@ -223,6 +224,22 @@ public static InetSocketAddress createSocketAddr(String target,
223224
}
224225
target = target.trim();
225226
boolean hasScheme = target.contains("://");
227+
if (StringUtils.countMatches(target, ":") > 2) {
228+
// if scheme exists in the target
229+
// for example : https://ffff:ffff:ffff:ffff::1:XXXXX
230+
// we have to form https://[ffff:ffff:ffff:ffff::1]:XXXXX
231+
if (hasScheme) {
232+
int i = target.lastIndexOf("/");
233+
String scheme = target.substring(0, i + 1);
234+
String ipAddrWithPort = target.substring(i + 1);
235+
target = scheme + normalizeV6Address(ipAddrWithPort);
236+
} else {
237+
// if scheme does not exists in the target
238+
// for example : ffff:ffff:ffff:ffff::1:XXXXX
239+
// we have to form [ffff:ffff:ffff:ffff::1]:XXXXX
240+
target = normalizeV6Address(target);
241+
}
242+
}
226243
URI uri = createURI(target, hasScheme, helpText, useCacheIfPresent);
227244

228245
String host = uri.getHost();
@@ -275,6 +292,24 @@ private static URI createURI(String target,
275292
return uri;
276293
}
277294

295+
public static String normalizeV6Address(String target) {
296+
if (!target.startsWith("[")) {
297+
if (target.contains("%")) {
298+
int i = target.lastIndexOf('%');
299+
target = target.trim();
300+
String port = target.substring(target.lastIndexOf(":") + 1);
301+
String addr = target.substring(0, i);
302+
target = "[" + addr + "]" + ":" + port;
303+
} else {
304+
int i = target.lastIndexOf(':');
305+
String port = target.substring(target.lastIndexOf(":") + 1);
306+
String addr = target.substring(0, i);
307+
target = "[" + addr + "]" + ":" + port;
308+
}
309+
}
310+
return target;
311+
}
312+
278313
/**
279314
* Create a socket address with the given host and port. The hostname
280315
* might be replaced with another host that was set via

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/net/TestNetUtils.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,4 +817,41 @@ private <T> void assertBetterArrayEquals(T[] expect, T[]got) {
817817
String gotStr = StringUtils.join(got, ", ");
818818
assertEquals(expectStr, gotStr);
819819
}
820+
821+
@Test
822+
public void testCreateSocketAddressWithIPV6() throws Throwable {
823+
String ipv6Address = "2a03:2880:2130:cf05:face:b00c:0:1";
824+
String ipv6WithPort = ipv6Address + ":12345";
825+
826+
InetSocketAddress addr = NetUtils.createSocketAddr(ipv6WithPort,
827+
1000, "myconfig");
828+
assertEquals("[" + ipv6Address + "]", addr.getHostName());
829+
assertEquals(12345, addr.getPort());
830+
831+
String ipv6SampleAddressWithScope = ipv6Address + "%2";
832+
ipv6WithPort = ipv6SampleAddressWithScope + ":12345";
833+
addr = NetUtils.createSocketAddr(ipv6WithPort, 1000, "myconfig");
834+
assertEquals("[" + ipv6Address + "]", addr.getHostName());
835+
assertEquals(12345, addr.getPort());
836+
837+
ipv6Address = "[2a03:2880:2130:cf05:face:b00c:0:1]";
838+
ipv6WithPort = ipv6Address + ":12345";
839+
840+
addr = NetUtils.createSocketAddr(ipv6WithPort, 1000, "myconfig");
841+
assertEquals(ipv6Address, addr.getHostName());
842+
assertEquals(12345, addr.getPort());
843+
844+
String ipv6AddressWithScheme =
845+
"https://2a03:2880:2130:cf05:face:b00c:0:1:12345";
846+
addr = NetUtils.createSocketAddr(ipv6AddressWithScheme, 1000,
847+
"myconfig");
848+
assertEquals(ipv6Address, addr.getHostName());
849+
assertEquals(12345, addr.getPort());
850+
851+
ipv6AddressWithScheme = "https://[2a03:2880:2130:cf05:face:b00c:0:1]:12345";
852+
addr = NetUtils.createSocketAddr(ipv6AddressWithScheme, 1000,
853+
"myconfig");
854+
assertEquals(ipv6Address, addr.getHostName());
855+
assertEquals(12345, addr.getPort());
856+
}
820857
}

0 commit comments

Comments
 (0)