From commits-return-8445-archive-asf-public=cust-asf.ponee.io@zookeeper.apache.org Mon Jul 13 10:10:42 2020 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [207.244.88.153]) by mx-eu-01.ponee.io (Postfix) with SMTP id 6569118037A for ; Mon, 13 Jul 2020 12:10:42 +0200 (CEST) Received: (qmail 25738 invoked by uid 500); 13 Jul 2020 10:10:41 -0000 Mailing-List: contact commits-help@zookeeper.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@zookeeper.apache.org Delivered-To: mailing list commits@zookeeper.apache.org Received: (qmail 25726 invoked by uid 99); 13 Jul 2020 10:10:41 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 13 Jul 2020 10:10:41 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id 8A756811C0; Mon, 13 Jul 2020 10:10:41 +0000 (UTC) Date: Mon, 13 Jul 2020 10:10:41 +0000 To: "commits@zookeeper.apache.org" Subject: [zookeeper] branch master updated: ZOOKEEPER-3878: Client connection fails if IPV6 is not enclosed in square brackets MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Message-ID: <159463504140.20367.12100859222062934217@gitbox.apache.org> From: eolivelli@apache.org X-Git-Host: gitbox.apache.org X-Git-Repo: zookeeper X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: 6ab1822ec431bb3309021c1ddc613a5eaa28d83b X-Git-Newrev: f362313860401024b7141489e66ee76af442eb76 X-Git-Rev: f362313860401024b7141489e66ee76af442eb76 X-Git-NotificationType: ref_changed_plus_diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated This is an automated email from the ASF dual-hosted git repository. eolivelli pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/zookeeper.git The following commit(s) were added to refs/heads/master by this push: new f362313 ZOOKEEPER-3878: Client connection fails if IPV6 is not enclosed in square brackets f362313 is described below commit f362313860401024b7141489e66ee76af442eb76 Author: Mohammad Arshad 72626 AuthorDate: Mon Jul 13 12:10:05 2020 +0200 ZOOKEEPER-3878: Client connection fails if IPV6 is not enclosed in square brackets Author: Mohammad Arshad 72626 Reviewers: Enrico Olivelli Closes #1398 from arshadmohammad/ZOOKEEPER-3878-master --- .../zookeeper/client/ConnectStringParser.java | 19 +++++---- .../java/org/apache/zookeeper/common/NetUtils.java | 44 +++++++++++++++++++++ .../org/apache/zookeeper/common/NetUtilsTest.java | 45 ++++++++++++++++++++++ .../zookeeper/test/ConnectStringParserTest.java | 22 +++++++++++ 4 files changed, 123 insertions(+), 7 deletions(-) diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/client/ConnectStringParser.java b/zookeeper-server/src/main/java/org/apache/zookeeper/client/ConnectStringParser.java index 2cea78b..d677b69 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/client/ConnectStringParser.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/client/ConnectStringParser.java @@ -22,9 +22,8 @@ import static org.apache.zookeeper.common.StringUtils.split; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; +import org.apache.zookeeper.common.NetUtils; import org.apache.zookeeper.common.PathUtils; -import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException; -import org.apache.zookeeper.server.util.ConfigUtils; /** * A parser for ZooKeeper Client connect strings. @@ -70,16 +69,22 @@ public final class ConnectStringParser { List hostsList = split(connectString, ","); for (String host : hostsList) { int port = DEFAULT_PORT; - try { - String[] hostAndPort = ConfigUtils.getHostAndPort(host); + String[] hostAndPort = NetUtils.getIPV6HostAndPort(host); + if (hostAndPort.length != 0) { host = hostAndPort[0]; if (hostAndPort.length == 2) { port = Integer.parseInt(hostAndPort[1]); } - } catch (ConfigException e) { - e.printStackTrace(); + } else { + int pidx = host.lastIndexOf(':'); + if (pidx >= 0) { + // otherwise : is at the end of the string, ignore + if (pidx < host.length() - 1) { + port = Integer.parseInt(host.substring(pidx + 1)); + } + host = host.substring(0, pidx); + } } - serverAddresses.add(InetSocketAddress.createUnresolved(host, port)); } } diff --git a/zookeeper-server/src/main/java/org/apache/zookeeper/common/NetUtils.java b/zookeeper-server/src/main/java/org/apache/zookeeper/common/NetUtils.java index cea12cc..be8cb9a 100644 --- a/zookeeper-server/src/main/java/org/apache/zookeeper/common/NetUtils.java +++ b/zookeeper-server/src/main/java/org/apache/zookeeper/common/NetUtils.java @@ -41,4 +41,48 @@ public class NetUtils { } } + /** + * Separates host and port from given host port string if host port string is enclosed + * within square bracket. + * + * @param hostPort host port string + * @return String[]{host, port} if host port string is host:port + * or String[] {host, port:port} if host port string is host:port:port + * or String[] {host} if host port string is host + * or String[]{} if not a ipv6 host port string. + */ + public static String[] getIPV6HostAndPort(String hostPort) { + if (hostPort.startsWith("[")) { + int i = hostPort.lastIndexOf(']'); + if (i < 0) { + throw new IllegalArgumentException( + hostPort + " starts with '[' but has no matching ']'"); + } + String host = hostPort.substring(1, i); + if (host.isEmpty()) { + throw new IllegalArgumentException(host + " is empty."); + } + if (hostPort.length() > i + 1) { + return getHostPort(hostPort, i, host); + } + return new String[] { host }; + } else { + //Not an IPV6 host port string + return new String[] {}; + } + } + + private static String[] getHostPort(String hostPort, int indexOfClosingBracket, String host) { + // [127::1]:2181 , check separator : exits + if (hostPort.charAt(indexOfClosingBracket + 1) != ':') { + throw new IllegalArgumentException(hostPort + " does not have : after ]"); + } + // [127::1]: scenario + if (indexOfClosingBracket + 2 == hostPort.length()) { + throw new IllegalArgumentException(hostPort + " doesn't have a port after colon."); + } + //do not include + String port = hostPort.substring(indexOfClosingBracket + 2); + return new String[] { host, port }; + } } diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/common/NetUtilsTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/common/NetUtilsTest.java index c61eeba..e06b7d1 100644 --- a/zookeeper-server/src/test/java/org/apache/zookeeper/common/NetUtilsTest.java +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/common/NetUtilsTest.java @@ -69,4 +69,49 @@ public class NetUtilsTest extends ZKTestCase { assertEquals("doesnt.exist.com:1234", NetUtils.formatInetAddr(isa)); } + @Test(expected = IllegalArgumentException.class) + public void tetGetIPV6HostAndPort_WhenHostDoesNotEndWithBracket() { + NetUtils.getIPV6HostAndPort("[2001:0db8:85a3:0000:0000:8a2e:0370:7334:443"); + } + + @Test(expected = IllegalArgumentException.class) + public void tetGetIPV6HostAndPort_WhenNoPortAfterColon() { + NetUtils.getIPV6HostAndPort("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:"); + } + + @Test(expected = IllegalArgumentException.class) + public void tetGetIPV6HostAndPort_WhenPortIsNotSeparatedProperly() { + NetUtils.getIPV6HostAndPort("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]2181"); + } + + @Test(expected = IllegalArgumentException.class) + public void tetGetIPV6HostAndPort_WhenHostIsEmpty() { + NetUtils.getIPV6HostAndPort("[]:2181"); + } + + @Test + public void tetGetIPV6HostAndPort_EmptyStringArrayIfDoesNotStartWithBracket() { + String[] ipv6HostAndPort = + NetUtils.getIPV6HostAndPort("2001:0db8:85a3:0000:0000:8a2e:0370:7334]"); + assertEquals(0, ipv6HostAndPort.length); + } + + @Test + public void tetGetIPV6HostAndPort_ReturnHostPort() { + String[] ipv6HostAndPort = + NetUtils.getIPV6HostAndPort("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:2181"); + assertEquals(2, ipv6HostAndPort.length); + assertEquals("2001:0db8:85a3:0000:0000:8a2e:0370:7334", ipv6HostAndPort[0]); + assertEquals("2181", ipv6HostAndPort[1]); + } + + @Test + public void tetGetIPV6HostAndPort_ReturnHostPortPort() { + String[] ipv6HostAndPort = + NetUtils.getIPV6HostAndPort("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:2181:3181"); + assertEquals(2, ipv6HostAndPort.length); + assertEquals("2001:0db8:85a3:0000:0000:8a2e:0370:7334", ipv6HostAndPort[0]); + assertEquals("2181:3181", ipv6HostAndPort[1]); + } + } diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/ConnectStringParserTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/ConnectStringParserTest.java index 066e0f3..e1048f2 100644 --- a/zookeeper-server/src/test/java/org/apache/zookeeper/test/ConnectStringParserTest.java +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/ConnectStringParserTest.java @@ -21,6 +21,7 @@ package org.apache.zookeeper.test; import static org.junit.Assert.assertEquals; import org.apache.zookeeper.ZKTestCase; import org.apache.zookeeper.client.ConnectStringParser; +import org.junit.Assert; import org.junit.Test; public class ConnectStringParserTest extends ZKTestCase { @@ -85,4 +86,25 @@ public class ConnectStringParserTest extends ZKTestCase { assertEquals(expected, parser.getChrootPath()); } + @Test + public void testParseIPV6ConnectionString() { + String servers = "[127::1],127.0.10.2"; + ConnectStringParser parser = new ConnectStringParser(servers); + + Assert.assertEquals("127::1", parser.getServerAddresses().get(0).getHostString()); + Assert.assertEquals("127.0.10.2", parser.getServerAddresses().get(1).getHostString()); + Assert.assertEquals(2181, parser.getServerAddresses().get(0).getPort()); + Assert.assertEquals(2181, parser.getServerAddresses().get(1).getPort()); + + servers = "[127::1]:2181,[127::2]:2182,[127::3]:2183"; + parser = new ConnectStringParser(servers); + + Assert.assertEquals("127::1", parser.getServerAddresses().get(0).getHostString()); + Assert.assertEquals("127::2", parser.getServerAddresses().get(1).getHostString()); + Assert.assertEquals("127::3", parser.getServerAddresses().get(2).getHostString()); + Assert.assertEquals(2181, parser.getServerAddresses().get(0).getPort()); + Assert.assertEquals(2182, parser.getServerAddresses().get(1).getPort()); + Assert.assertEquals(2183, parser.getServerAddresses().get(2).getPort()); + } + }