HADOOP-17542. IPV6 support in Netutils#createSocketAddress (#3217)

* HADOOP-17542. IPV6 support in Netutils#createSocketAddress

* HADOOP-17542. IPV6 support in Netutils#createSocketAddress, review comments
This commit is contained in:
Renukaprasad C 2021-08-10 16:20:22 +05:30 committed by GitHub
parent 7118db5ee3
commit c0f0b33e40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 1 deletions

View File

@ -199,8 +199,16 @@ public class Path
int start = 0; int start = 0;
// parse uri scheme, if any // parse uri scheme, if any
int colon = pathString.indexOf(':'); int colon = -1;
int slash = pathString.indexOf('/'); int slash = pathString.indexOf('/');
if (StringUtils.countMatches(pathString, ":") > 2) {
//In case of IPv6 address, we should be able to parse the scheme
// correctly (This will ensure to parse path with & without scheme
// correctly in IPv6).
colon = pathString.indexOf(":/");
} else {
colon = pathString.indexOf(':');
}
if ((colon != -1) && if ((colon != -1) &&
((slash == -1) || (colon < slash))) { // has a scheme ((slash == -1) || (colon < slash))) { // has a scheme
scheme = pathString.substring(0, colon); scheme = pathString.substring(0, colon);

View File

@ -45,6 +45,7 @@ import java.util.concurrent.ConcurrentHashMap;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.security.AccessControlException; import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.thirdparty.com.google.common.cache.Cache; import org.apache.hadoop.thirdparty.com.google.common.cache.Cache;
import org.apache.hadoop.thirdparty.com.google.common.cache.CacheBuilder; import org.apache.hadoop.thirdparty.com.google.common.cache.CacheBuilder;
@ -223,6 +224,22 @@ public class NetUtils {
} }
target = target.trim(); target = target.trim();
boolean hasScheme = target.contains("://"); boolean hasScheme = target.contains("://");
if (StringUtils.countMatches(target, ":") > 2) {
// if scheme exists in the target
// for example : https://ffff:ffff:ffff:ffff::1:XXXXX
// we have to form https://[ffff:ffff:ffff:ffff::1]:XXXXX
if (hasScheme) {
int i = target.lastIndexOf("/");
String scheme = target.substring(0, i + 1);
String ipAddrWithPort = target.substring(i + 1);
target = scheme + normalizeV6Address(ipAddrWithPort);
} else {
// if scheme does not exists in the target
// for example : ffff:ffff:ffff:ffff::1:XXXXX
// we have to form [ffff:ffff:ffff:ffff::1]:XXXXX
target = normalizeV6Address(target);
}
}
URI uri = createURI(target, hasScheme, helpText, useCacheIfPresent); URI uri = createURI(target, hasScheme, helpText, useCacheIfPresent);
String host = uri.getHost(); String host = uri.getHost();
@ -275,6 +292,24 @@ public class NetUtils {
return uri; return uri;
} }
public static String normalizeV6Address(String target) {
if (!target.startsWith("[")) {
if (target.contains("%")) {
int i = target.lastIndexOf('%');
target = target.trim();
String port = target.substring(target.lastIndexOf(":") + 1);
String addr = target.substring(0, i);
target = "[" + addr + "]" + ":" + port;
} else {
int i = target.lastIndexOf(':');
String port = target.substring(target.lastIndexOf(":") + 1);
String addr = target.substring(0, i);
target = "[" + addr + "]" + ":" + port;
}
}
return target;
}
/** /**
* Create a socket address with the given host and port. The hostname * Create a socket address with the given host and port. The hostname
* might be replaced with another host that was set via * might be replaced with another host that was set via

View File

@ -817,4 +817,41 @@ public class TestNetUtils {
String gotStr = StringUtils.join(got, ", "); String gotStr = StringUtils.join(got, ", ");
assertEquals(expectStr, gotStr); assertEquals(expectStr, gotStr);
} }
@Test
public void testCreateSocketAddressWithIPV6() throws Throwable {
String ipv6Address = "2a03:2880:2130:cf05:face:b00c:0:1";
String ipv6WithPort = ipv6Address + ":12345";
InetSocketAddress addr = NetUtils.createSocketAddr(ipv6WithPort,
1000, "myconfig");
assertEquals("[" + ipv6Address + "]", addr.getHostName());
assertEquals(12345, addr.getPort());
String ipv6SampleAddressWithScope = ipv6Address + "%2";
ipv6WithPort = ipv6SampleAddressWithScope + ":12345";
addr = NetUtils.createSocketAddr(ipv6WithPort, 1000, "myconfig");
assertEquals("[" + ipv6Address + "]", addr.getHostName());
assertEquals(12345, addr.getPort());
ipv6Address = "[2a03:2880:2130:cf05:face:b00c:0:1]";
ipv6WithPort = ipv6Address + ":12345";
addr = NetUtils.createSocketAddr(ipv6WithPort, 1000, "myconfig");
assertEquals(ipv6Address, addr.getHostName());
assertEquals(12345, addr.getPort());
String ipv6AddressWithScheme =
"https://2a03:2880:2130:cf05:face:b00c:0:1:12345";
addr = NetUtils.createSocketAddr(ipv6AddressWithScheme, 1000,
"myconfig");
assertEquals(ipv6Address, addr.getHostName());
assertEquals(12345, addr.getPort());
ipv6AddressWithScheme = "https://[2a03:2880:2130:cf05:face:b00c:0:1]:12345";
addr = NetUtils.createSocketAddr(ipv6AddressWithScheme, 1000,
"myconfig");
assertEquals(ipv6Address, addr.getHostName());
assertEquals(12345, addr.getPort());
}
} }