1 /* 2 * Copyright 2015 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc; 18 19 import com.google.common.base.Preconditions; 20 import java.lang.annotation.Documented; 21 import java.lang.annotation.Retention; 22 import java.lang.annotation.RetentionPolicy; 23 import java.net.SocketAddress; 24 import java.util.ArrayList; 25 import java.util.Collections; 26 import java.util.List; 27 28 /** 29 * A group of {@link SocketAddress}es that are considered equivalent when channel makes connections. 30 * 31 * <p>Usually the addresses are addresses resolved from the same host name, and connecting to any of 32 * them is equally sufficient. They do have order. An address appears earlier on the list is likely 33 * to be tried earlier. 34 */ 35 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1770") 36 public final class EquivalentAddressGroup { 37 38 /** 39 * The authority to be used when constructing Subchannels for this EquivalentAddressGroup. 40 * However, if the channel has overridden authority via 41 * {@link ManagedChannelBuilder#overrideAuthority(String)}, the transport will use the channel's 42 * authority override. 43 * 44 * <p>The authority <strong>must</strong> be from a trusted source, because if the authority is 45 * tampered with, RPCs may be sent to attackers which may leak sensitive user data. If the 46 * authority was acquired by doing I/O, the communication must be authenticated (e.g., via TLS). 47 * Recognize that the server that provided the authority can trivially impersonate the service. 48 */ 49 @Attr 50 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/6138") 51 public static final Attributes.Key<String> ATTR_AUTHORITY_OVERRIDE = 52 Attributes.Key.create("io.grpc.EquivalentAddressGroup.ATTR_AUTHORITY_OVERRIDE"); 53 private final List<SocketAddress> addrs; 54 private final Attributes attrs; 55 56 /** 57 * {@link SocketAddress} docs say that the addresses are immutable, so we cache the hashCode. 58 */ 59 private final int hashCode; 60 61 /** 62 * List constructor without {@link Attributes}. 63 */ EquivalentAddressGroup(List<SocketAddress> addrs)64 public EquivalentAddressGroup(List<SocketAddress> addrs) { 65 this(addrs, Attributes.EMPTY); 66 } 67 68 /** 69 * List constructor with {@link Attributes}. 70 */ EquivalentAddressGroup(List<SocketAddress> addrs, @Attr Attributes attrs)71 public EquivalentAddressGroup(List<SocketAddress> addrs, @Attr Attributes attrs) { 72 Preconditions.checkArgument(!addrs.isEmpty(), "addrs is empty"); 73 this.addrs = Collections.unmodifiableList(new ArrayList<>(addrs)); 74 this.attrs = Preconditions.checkNotNull(attrs, "attrs"); 75 // Attributes may contain mutable objects, which means Attributes' hashCode may change over 76 // time, thus we don't cache Attributes' hashCode. 77 hashCode = this.addrs.hashCode(); 78 } 79 80 /** 81 * Singleton constructor without Attributes. 82 */ EquivalentAddressGroup(SocketAddress addr)83 public EquivalentAddressGroup(SocketAddress addr) { 84 this(addr, Attributes.EMPTY); 85 } 86 87 /** 88 * Singleton constructor with Attributes. 89 */ EquivalentAddressGroup(SocketAddress addr, @Attr Attributes attrs)90 public EquivalentAddressGroup(SocketAddress addr, @Attr Attributes attrs) { 91 this(Collections.singletonList(addr), attrs); 92 } 93 94 /** 95 * Returns an immutable list of the addresses. 96 */ getAddresses()97 public List<SocketAddress> getAddresses() { 98 return addrs; 99 } 100 101 /** 102 * Returns the attributes. 103 */ 104 @Attr getAttributes()105 public Attributes getAttributes() { 106 return attrs; 107 } 108 109 @Override toString()110 public String toString() { 111 // TODO(zpencer): Summarize return value if addr is very large 112 return "[" + addrs + "/" + attrs + "]"; 113 } 114 115 @Override hashCode()116 public int hashCode() { 117 // Avoids creating an iterator on the underlying array list. 118 return hashCode; 119 } 120 121 /** 122 * Returns true if the given object is also an {@link EquivalentAddressGroup} with an equal 123 * address list and equal attribute values. 124 * 125 * <p>Note that if the attributes include mutable values, it is possible for two objects to be 126 * considered equal at one point in time and not equal at another (due to concurrent mutation of 127 * attribute values). 128 */ 129 @Override equals(Object other)130 public boolean equals(Object other) { 131 if (!(other instanceof EquivalentAddressGroup)) { 132 return false; 133 } 134 EquivalentAddressGroup that = (EquivalentAddressGroup) other; 135 if (addrs.size() != that.addrs.size()) { 136 return false; 137 } 138 // Avoids creating an iterator on the underlying array list. 139 for (int i = 0; i < addrs.size(); i++) { 140 if (!addrs.get(i).equals(that.addrs.get(i))) { 141 return false; 142 } 143 } 144 if (!attrs.equals(that.attrs)) { 145 return false; 146 } 147 return true; 148 } 149 150 /** 151 * Annotation for {@link EquivalentAddressGroup}'s attributes. It follows the annotation semantics 152 * defined by {@link Attributes}. 153 */ 154 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/4972") 155 @Retention(RetentionPolicy.SOURCE) 156 @Documented 157 public @interface Attr {} 158 } 159