2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 import android.net.ProxyProperties;
20 import android.os.Parcelable;
21 import android.os.Parcel;
22 import android.text.TextUtils;
24 import java.net.InetAddress;
25 import java.net.UnknownHostException;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Collections;
31 * Describes the properties of a network link.
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.
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.
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.
52 public class LinkProperties implements Parcelable {
55 private Collection<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>();
56 private Collection<InetAddress> mDnses = new ArrayList<InetAddress>();
57 private Collection<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
58 private ProxyProperties mHttpProxy;
60 public static class CompareResult<T> {
61 public Collection<T> removed = new ArrayList<T>();
62 public Collection<T> added = new ArrayList<T>();
65 public String toString() {
66 String retVal = "removed=[";
67 for (T addr : removed) retVal += addr.toString() + ",";
68 retVal += "] added=[";
69 for (T addr : added) retVal += addr.toString() + ",";
75 public LinkProperties() {
79 // copy constructor instead of clone
80 public LinkProperties(LinkProperties source) {
82 mIfaceName = source.getInterfaceName();
83 mLinkAddresses = source.getLinkAddresses();
84 mDnses = source.getDnses();
85 mRoutes = source.getRoutes();
86 mHttpProxy = (source.getHttpProxy() == null) ?
87 null : new ProxyProperties(source.getHttpProxy());
91 public void setInterfaceName(String iface) {
95 public String getInterfaceName() {
99 public Collection<InetAddress> getAddresses() {
100 Collection<InetAddress> addresses = new ArrayList<InetAddress>();
101 for (LinkAddress linkAddress : mLinkAddresses) {
102 addresses.add(linkAddress.getAddress());
104 return Collections.unmodifiableCollection(addresses);
107 public void addLinkAddress(LinkAddress address) {
108 if (address != null) mLinkAddresses.add(address);
111 public Collection<LinkAddress> getLinkAddresses() {
112 return Collections.unmodifiableCollection(mLinkAddresses);
115 public void addDns(InetAddress dns) {
116 if (dns != null) mDnses.add(dns);
119 public Collection<InetAddress> getDnses() {
120 return Collections.unmodifiableCollection(mDnses);
123 public void addRoute(RouteInfo route) {
124 if (route != null) mRoutes.add(route);
126 public Collection<RouteInfo> getRoutes() {
127 return Collections.unmodifiableCollection(mRoutes);
130 public void setHttpProxy(ProxyProperties proxy) {
133 public ProxyProperties getHttpProxy() {
137 public void clear() {
139 mLinkAddresses.clear();
146 * Implement the Parcelable interface
149 public int describeContents() {
154 public String toString() {
155 String ifaceName = (mIfaceName == null ? "" : "InterfaceName: " + mIfaceName + " ");
157 String linkAddresses = "LinkAddresses: [";
158 for (LinkAddress addr : mLinkAddresses) linkAddresses += addr.toString() + ",";
159 linkAddresses += "] ";
161 String dns = "DnsAddresses: [";
162 for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ",";
165 String routes = "Routes: [";
166 for (RouteInfo route : mRoutes) routes += route.toString() + ",";
168 String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " ");
170 return ifaceName + linkAddresses + routes + dns + proxy;
174 * Compares this {@code LinkProperties} interface name against the target
176 * @param target LinkProperties to compare.
177 * @return {@code true} if both are identical, {@code false} otherwise.
179 public boolean isIdenticalInterfaceName(LinkProperties target) {
180 return TextUtils.equals(getInterfaceName(), target.getInterfaceName());
184 * Compares this {@code LinkProperties} interface name against the target
186 * @param target LinkProperties to compare.
187 * @return {@code true} if both are identical, {@code false} otherwise.
189 public boolean isIdenticalAddresses(LinkProperties target) {
190 Collection<InetAddress> targetAddresses = target.getAddresses();
191 Collection<InetAddress> sourceAddresses = getAddresses();
192 return (sourceAddresses.size() == targetAddresses.size()) ?
193 sourceAddresses.containsAll(targetAddresses) : false;
197 * Compares this {@code LinkProperties} DNS addresses against the target
199 * @param target LinkProperties to compare.
200 * @return {@code true} if both are identical, {@code false} otherwise.
202 public boolean isIdenticalDnses(LinkProperties target) {
203 Collection<InetAddress> targetDnses = target.getDnses();
204 return (mDnses.size() == targetDnses.size()) ?
205 mDnses.containsAll(targetDnses) : false;
209 * Compares this {@code LinkProperties} Routes against the target
211 * @param target LinkProperties to compare.
212 * @return {@code true} if both are identical, {@code false} otherwise.
214 public boolean isIdenticalRoutes(LinkProperties target) {
215 Collection<RouteInfo> targetRoutes = target.getRoutes();
216 return (mRoutes.size() == targetRoutes.size()) ?
217 mRoutes.containsAll(targetRoutes) : false;
221 * Compares this {@code LinkProperties} HttpProxy against the target
223 * @param target LinkProperties to compare.
224 * @return {@code true} if both are identical, {@code false} otherwise.
226 public boolean isIdenticalHttpProxy(LinkProperties target) {
227 return getHttpProxy() == null ? target.getHttpProxy() == null :
228 getHttpProxy().equals(target.getHttpProxy());
233 * Compares this {@code LinkProperties} instance against the target
234 * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
235 * all their fields are equal in values.
237 * For collection fields, such as mDnses, containsAll() is used to check
238 * if two collections contains the same elements, independent of order.
239 * There are two thoughts regarding containsAll()
240 * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal.
241 * 2. Worst case performance is O(n^2).
243 * @param obj the object to be tested for equality.
244 * @return {@code true} if both objects are equal, {@code false} otherwise.
246 public boolean equals(Object obj) {
247 if (this == obj) return true;
249 if (!(obj instanceof LinkProperties)) return false;
251 LinkProperties target = (LinkProperties) obj;
253 return isIdenticalInterfaceName(target) &&
254 isIdenticalAddresses(target) &&
255 isIdenticalDnses(target) &&
256 isIdenticalRoutes(target) &&
257 isIdenticalHttpProxy(target);
261 * Return two lists, a list of addresses that would be removed from
262 * mLinkAddresses and a list of addresses that would be added to
263 * mLinkAddress which would then result in target and mLinkAddresses
264 * being the same list.
266 * @param target is a LinkProperties with the new list of addresses
267 * @return the removed and added lists.
269 public CompareResult<LinkAddress> compareAddresses(LinkProperties target) {
271 * Duplicate the LinkAddresses into removed, we will be removing
272 * address which are common between mLinkAddresses and target
273 * leaving the addresses that are different. And address which
274 * are in target but not in mLinkAddresses are placed in the
277 CompareResult<LinkAddress> result = new CompareResult<LinkAddress>();
278 result.removed = new ArrayList<LinkAddress>(mLinkAddresses);
279 result.added.clear();
280 if (target != null) {
281 for (LinkAddress newAddress : target.getLinkAddresses()) {
282 if (! result.removed.remove(newAddress)) {
283 result.added.add(newAddress);
291 * Return two lists, a list of dns addresses that would be removed from
292 * mDnses and a list of addresses that would be added to
293 * mDnses which would then result in target and mDnses
294 * being the same list.
296 * @param target is a LinkProperties with the new list of dns addresses
297 * @return the removed and added lists.
299 public CompareResult<InetAddress> compareDnses(LinkProperties target) {
301 * Duplicate the InetAddresses into removed, we will be removing
302 * dns address which are common between mDnses and target
303 * leaving the addresses that are different. And dns address which
304 * are in target but not in mDnses are placed in the
307 CompareResult<InetAddress> result = new CompareResult<InetAddress>();
309 result.removed = new ArrayList<InetAddress>(mDnses);
310 result.added.clear();
311 if (target != null) {
312 for (InetAddress newAddress : target.getDnses()) {
313 if (! result.removed.remove(newAddress)) {
314 result.added.add(newAddress);
322 * Return two lists, a list of routes that would be removed from
323 * mRoutes and a list of routes that would be added to
324 * mRoutes which would then result in target and mRoutes
325 * being the same list.
327 * @param target is a LinkProperties with the new list of routes
328 * @return the removed and added lists.
330 public CompareResult<RouteInfo> compareRoutes(LinkProperties target) {
332 * Duplicate the RouteInfos into removed, we will be removing
333 * routes which are common between mDnses and target
334 * leaving the routes that are different. And route address which
335 * are in target but not in mRoutes are placed in added.
337 CompareResult<RouteInfo> result = new CompareResult<RouteInfo>();
339 result.removed = new ArrayList<RouteInfo>(mRoutes);
340 result.added.clear();
341 if (target != null) {
342 for (RouteInfo r : target.getRoutes()) {
343 if (! result.removed.remove(r)) {
354 * generate hashcode based on significant fields
355 * Equal objects must produce the same hash code, while unequal objects
356 * may have the same hash codes.
358 public int hashCode() {
359 return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
360 + mLinkAddresses.size() * 31
362 + mRoutes.size() * 41
363 + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode()));
367 * Implement the Parcelable interface.
370 public void writeToParcel(Parcel dest, int flags) {
371 dest.writeString(getInterfaceName());
372 dest.writeInt(mLinkAddresses.size());
373 for(LinkAddress linkAddress : mLinkAddresses) {
374 dest.writeParcelable(linkAddress, flags);
377 dest.writeInt(mDnses.size());
378 for(InetAddress d : mDnses) {
379 dest.writeByteArray(d.getAddress());
382 dest.writeInt(mRoutes.size());
383 for(RouteInfo route : mRoutes) {
384 dest.writeParcelable(route, flags);
387 if (mHttpProxy != null) {
388 dest.writeByte((byte)1);
389 dest.writeParcelable(mHttpProxy, flags);
391 dest.writeByte((byte)0);
396 * Implement the Parcelable interface.
399 public static final Creator<LinkProperties> CREATOR =
400 new Creator<LinkProperties>() {
401 public LinkProperties createFromParcel(Parcel in) {
402 LinkProperties netProp = new LinkProperties();
403 String iface = in.readString();
406 netProp.setInterfaceName(iface);
407 } catch (Exception e) {
411 int addressCount = in.readInt();
412 for (int i=0; i<addressCount; i++) {
413 netProp.addLinkAddress((LinkAddress)in.readParcelable(null));
415 addressCount = in.readInt();
416 for (int i=0; i<addressCount; i++) {
418 netProp.addDns(InetAddress.getByAddress(in.createByteArray()));
419 } catch (UnknownHostException e) { }
421 addressCount = in.readInt();
422 for (int i=0; i<addressCount; i++) {
423 netProp.addRoute((RouteInfo)in.readParcelable(null));
425 if (in.readByte() == 1) {
426 netProp.setHttpProxy((ProxyProperties)in.readParcelable(null));
431 public LinkProperties[] newArray(int size) {
432 return new LinkProperties[size];