LinkProperties.java revision be2b058ec1e11e1d33b6d03230c21e5d2d7ac40c
1/* 2 * Copyright (C) 2010 The Android Open Source Project 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 17package android.net; 18 19import android.net.ProxyProperties; 20import android.os.Parcelable; 21import android.os.Parcel; 22import android.text.TextUtils; 23 24import java.net.InetAddress; 25import java.net.UnknownHostException; 26import java.util.ArrayList; 27import java.util.Collection; 28import java.util.Collections; 29 30/** 31 * Describes the properties of a network link. 32 * 33 * A link represents a connection to a network. 34 * It may have multiple addresses and multiple gateways, 35 * multiple dns servers but only one http proxy. 36 * 37 * Because it's a single network, the dns's 38 * are interchangeable and don't need associating with 39 * particular addresses. The gateways similarly don't 40 * need associating with particular addresses. 41 * 42 * A dual stack interface works fine in this model: 43 * each address has it's own prefix length to describe 44 * the local network. The dns servers all return 45 * both v4 addresses and v6 addresses regardless of the 46 * address family of the server itself (rfc4213) and we 47 * don't care which is used. The gateways will be 48 * selected based on the destination address and the 49 * source address has no relavence. 50 * @hide 51 */ 52public class LinkProperties implements Parcelable { 53 54 String mIfaceName; 55 private Collection<LinkAddress> mLinkAddresses; 56 private Collection<InetAddress> mDnses; 57 private Collection<RouteInfo> mRoutes; 58 private ProxyProperties mHttpProxy; 59 60 public LinkProperties() { 61 clear(); 62 } 63 64 // copy constructor instead of clone 65 public LinkProperties(LinkProperties source) { 66 if (source != null) { 67 mIfaceName = source.getInterfaceName(); 68 mLinkAddresses = source.getLinkAddresses(); 69 mDnses = source.getDnses(); 70 mRoutes = source.getRoutes(); 71 mHttpProxy = (source.getHttpProxy() == null) ? 72 null : new ProxyProperties(source.getHttpProxy()); 73 } 74 } 75 76 public void setInterfaceName(String iface) { 77 mIfaceName = iface; 78 } 79 80 public String getInterfaceName() { 81 return mIfaceName; 82 } 83 84 public Collection<InetAddress> getAddresses() { 85 Collection<InetAddress> addresses = new ArrayList<InetAddress>(); 86 for (LinkAddress linkAddress : mLinkAddresses) { 87 addresses.add(linkAddress.getAddress()); 88 } 89 return Collections.unmodifiableCollection(addresses); 90 } 91 92 public void addLinkAddress(LinkAddress address) { 93 if (address != null) mLinkAddresses.add(address); 94 } 95 96 public Collection<LinkAddress> getLinkAddresses() { 97 return Collections.unmodifiableCollection(mLinkAddresses); 98 } 99 100 public void addDns(InetAddress dns) { 101 if (dns != null) mDnses.add(dns); 102 } 103 104 public Collection<InetAddress> getDnses() { 105 return Collections.unmodifiableCollection(mDnses); 106 } 107 108 public void addRoute(RouteInfo route) { 109 if (route != null) mRoutes.add(route); 110 } 111 public Collection<RouteInfo> getRoutes() { 112 return Collections.unmodifiableCollection(mRoutes); 113 } 114 115 public void setHttpProxy(ProxyProperties proxy) { 116 mHttpProxy = proxy; 117 } 118 public ProxyProperties getHttpProxy() { 119 return mHttpProxy; 120 } 121 122 public void clear() { 123 mIfaceName = null; 124 mLinkAddresses = new ArrayList<LinkAddress>(); 125 mDnses = new ArrayList<InetAddress>(); 126 mRoutes = new ArrayList<RouteInfo>(); 127 mHttpProxy = null; 128 } 129 130 /** 131 * Implement the Parcelable interface 132 * @hide 133 */ 134 public int describeContents() { 135 return 0; 136 } 137 138 @Override 139 public String toString() { 140 String ifaceName = (mIfaceName == null ? "" : "InterfaceName: " + mIfaceName + " "); 141 142 String linkAddresses = "LinkAddresses: ["; 143 for (LinkAddress addr : mLinkAddresses) linkAddresses += addr.toString() + ","; 144 linkAddresses += "] "; 145 146 String dns = "DnsAddresses: ["; 147 for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ","; 148 dns += "] "; 149 150 String routes = "Routes: ["; 151 for (RouteInfo route : mRoutes) routes += route.toString() + ","; 152 routes += "] "; 153 String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " "); 154 155 return ifaceName + linkAddresses + routes + dns + proxy; 156 } 157 158 159 @Override 160 /** 161 * Compares this {@code LinkProperties} instance against the target 162 * LinkProperties in {@code obj}. Two LinkPropertieses are equal if 163 * all their fields are equal in values. 164 * 165 * For collection fields, such as mDnses, containsAll() is used to check 166 * if two collections contains the same elements, independent of order. 167 * There are two thoughts regarding containsAll() 168 * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal. 169 * 2. Worst case performance is O(n^2). 170 * 171 * @param obj the object to be tested for equality. 172 * @return {@code true} if both objects are equal, {@code false} otherwise. 173 */ 174 public boolean equals(Object obj) { 175 if (this == obj) return true; 176 177 if (!(obj instanceof LinkProperties)) return false; 178 179 boolean sameAddresses; 180 boolean sameDnses; 181 boolean sameRoutes; 182 183 LinkProperties target = (LinkProperties) obj; 184 185 Collection<InetAddress> targetAddresses = target.getAddresses(); 186 Collection<InetAddress> sourceAddresses = getAddresses(); 187 sameAddresses = (sourceAddresses.size() == targetAddresses.size()) ? 188 sourceAddresses.containsAll(targetAddresses) : false; 189 190 Collection<InetAddress> targetDnses = target.getDnses(); 191 sameDnses = (mDnses.size() == targetDnses.size()) ? 192 mDnses.containsAll(targetDnses) : false; 193 194 Collection<RouteInfo> targetRoutes = target.getRoutes(); 195 sameRoutes = (mRoutes.size() == targetRoutes.size()) ? 196 mRoutes.containsAll(targetRoutes) : false; 197 198 return 199 sameAddresses && sameDnses && sameRoutes 200 && TextUtils.equals(getInterfaceName(), target.getInterfaceName()) 201 && (getHttpProxy() == null ? target.getHttpProxy() == null : 202 getHttpProxy().equals(target.getHttpProxy())); 203 } 204 205 @Override 206 /** 207 * generate hashcode based on significant fields 208 * Equal objects must produce the same hash code, while unequal objects 209 * may have the same hash codes. 210 */ 211 public int hashCode() { 212 return ((null == mIfaceName) ? 0 : mIfaceName.hashCode() 213 + mLinkAddresses.size() * 31 214 + mDnses.size() * 37 215 + mRoutes.size() * 41 216 + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode())); 217 } 218 219 /** 220 * Implement the Parcelable interface. 221 * @hide 222 */ 223 public void writeToParcel(Parcel dest, int flags) { 224 dest.writeString(getInterfaceName()); 225 dest.writeInt(mLinkAddresses.size()); 226 for(LinkAddress linkAddress : mLinkAddresses) { 227 dest.writeParcelable(linkAddress, flags); 228 } 229 230 dest.writeInt(mDnses.size()); 231 for(InetAddress d : mDnses) { 232 dest.writeByteArray(d.getAddress()); 233 } 234 235 dest.writeInt(mRoutes.size()); 236 for(RouteInfo route : mRoutes) { 237 dest.writeParcelable(route, flags); 238 } 239 240 if (mHttpProxy != null) { 241 dest.writeByte((byte)1); 242 dest.writeParcelable(mHttpProxy, flags); 243 } else { 244 dest.writeByte((byte)0); 245 } 246 } 247 248 /** 249 * Implement the Parcelable interface. 250 * @hide 251 */ 252 public static final Creator<LinkProperties> CREATOR = 253 new Creator<LinkProperties>() { 254 public LinkProperties createFromParcel(Parcel in) { 255 LinkProperties netProp = new LinkProperties(); 256 String iface = in.readString(); 257 if (iface != null) { 258 try { 259 netProp.setInterfaceName(iface); 260 } catch (Exception e) { 261 return null; 262 } 263 } 264 int addressCount = in.readInt(); 265 for (int i=0; i<addressCount; i++) { 266 netProp.addLinkAddress((LinkAddress)in.readParcelable(null)); 267 } 268 addressCount = in.readInt(); 269 for (int i=0; i<addressCount; i++) { 270 try { 271 netProp.addDns(InetAddress.getByAddress(in.createByteArray())); 272 } catch (UnknownHostException e) { } 273 } 274 addressCount = in.readInt(); 275 for (int i=0; i<addressCount; i++) { 276 netProp.addRoute((RouteInfo)in.readParcelable(null)); 277 } 278 if (in.readByte() == 1) { 279 netProp.setHttpProxy((ProxyProperties)in.readParcelable(null)); 280 } 281 return netProp; 282 } 283 284 public LinkProperties[] newArray(int size) { 285 return new LinkProperties[size]; 286 } 287 }; 288} 289