diff --git a/xds/src/main/java/io/grpc/xds/XdsClientWrapperForServerSds.java b/xds/src/main/java/io/grpc/xds/XdsClientWrapperForServerSds.java index 275c6a288e..d2674d263b 100644 --- a/xds/src/main/java/io/grpc/xds/XdsClientWrapperForServerSds.java +++ b/xds/src/main/java/io/grpc/xds/XdsClientWrapperForServerSds.java @@ -40,10 +40,8 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.ArrayList; -import java.util.Comparator; import java.util.HashSet; import java.util.List; -import java.util.PriorityQueue; import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -307,88 +305,55 @@ public final class XdsClientWrapperForServerSds { return cidrInt.equals(addrInt); } - private static class QueueElement { - FilterChain filterChain; - int indexOfMatchingPrefixRange; + private static int getMatchingPrefixLength( + FilterChainMatch filterChainMatch, InetAddress address, boolean forDestination) { + byte[] addressBytes = address.getAddress(); + boolean isIPv6 = address instanceof Inet6Address; + List cidrRanges = + forDestination + ? filterChainMatch.getPrefixRanges() + : filterChainMatch.getSourcePrefixRanges(); int matchingPrefixLength; - - public QueueElement(FilterChain filterChain, InetAddress address, boolean forDestination) { - this.filterChain = filterChain; - FilterChainMatch filterChainMatch = filterChain.getFilterChainMatch(); - byte[] addressBytes = address.getAddress(); - boolean isIPv6 = address instanceof Inet6Address; - List cidrRanges = - forDestination - ? filterChainMatch.getPrefixRanges() - : filterChainMatch.getSourcePrefixRanges(); - indexOfMatchingPrefixRange = -1; - if (cidrRanges.isEmpty()) { // if there is no CidrRange assume 0-length match - matchingPrefixLength = 0; - } else { - matchingPrefixLength = -1; - int index = 0; - for (CidrRange cidrRange : cidrRanges) { - InetAddress cidrAddr = cidrRange.getAddressPrefix(); - boolean cidrIsIpv6 = cidrAddr instanceof Inet6Address; - if (isIPv6 == cidrIsIpv6) { - byte[] cidrBytes = cidrAddr.getAddress(); - int prefixLen = cidrRange.getPrefixLen(); - if (isCidrMatching(cidrBytes, addressBytes, prefixLen) - && prefixLen > matchingPrefixLength) { - matchingPrefixLength = prefixLen; - indexOfMatchingPrefixRange = index; - } + if (cidrRanges.isEmpty()) { // if there is no CidrRange assume 0-length match + matchingPrefixLength = 0; + } else { + matchingPrefixLength = -1; + for (CidrRange cidrRange : cidrRanges) { + InetAddress cidrAddr = cidrRange.getAddressPrefix(); + boolean cidrIsIpv6 = cidrAddr instanceof Inet6Address; + if (isIPv6 == cidrIsIpv6) { + byte[] cidrBytes = cidrAddr.getAddress(); + int prefixLen = cidrRange.getPrefixLen(); + if (isCidrMatching(cidrBytes, addressBytes, prefixLen) + && prefixLen > matchingPrefixLength) { + matchingPrefixLength = prefixLen; } - index++; } } } - } - - private static final class QueueElementComparator implements Comparator { - - @Override - public int compare(QueueElement o1, QueueElement o2) { - // descending order for max heap - return o2.matchingPrefixLength - o1.matchingPrefixLength; - } - - @Override - public boolean equals(Object obj) { - return obj instanceof QueueElementComparator; - } - - @Override - public int hashCode() { - return super.hashCode(); - } + return matchingPrefixLength; } // use prefix_ranges (CIDR) and get the most specific matches private static List filterOnIpAddress( List filterChains, InetAddress address, boolean forDestination) { - PriorityQueue heap = new PriorityQueue<>(10, new QueueElementComparator()); - - for (FilterChain filterChain : filterChains) { - QueueElement element = new QueueElement(filterChain, address, forDestination); - - if (element.matchingPrefixLength >= 0) { - heap.add(element); - } - } - // get the top ones - ArrayList topOnes = new ArrayList<>(heap.size()); + // curent list of top ones + ArrayList topOnes = new ArrayList<>(filterChains.size()); int topMatchingPrefixLen = -1; - while (!heap.isEmpty()) { - QueueElement element = heap.remove(); - if (topMatchingPrefixLen == -1) { - topMatchingPrefixLen = element.matchingPrefixLength; - } else { - if (element.matchingPrefixLength < topMatchingPrefixLen) { - break; + for (FilterChain filterChain : filterChains) { + int currentMatchingPrefixLen = + getMatchingPrefixLength(filterChain.getFilterChainMatch(), address, forDestination); + + if (currentMatchingPrefixLen >= 0) { + if (currentMatchingPrefixLen < topMatchingPrefixLen) { + continue; } + if (currentMatchingPrefixLen > topMatchingPrefixLen) { + topMatchingPrefixLen = currentMatchingPrefixLen; + topOnes.clear(); + } + topOnes.add(filterChain); } - topOnes.add(element.filterChain); } return topOnes; }