OSDN Git Service

f2f0e825c00740dd4931a73aec02b047f8252dc4
[android-x86/frameworks-base.git] / core / java / android / net / LinkProperties.java
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
17 package android.net;
18
19 import android.net.ProxyProperties;
20 import android.os.Parcelable;
21 import android.os.Parcel;
22 import android.text.TextUtils;
23
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;
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  */
52 public class LinkProperties implements Parcelable {
53
54     String mIfaceName;
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;
59
60     public static class CompareAddressesResult {
61         public ArrayList<LinkAddress> removed = new ArrayList<LinkAddress>();
62         public ArrayList<LinkAddress> added = new ArrayList<LinkAddress>();
63
64         @Override
65         public String toString() {
66             String retVal = "removedAddresses=[";
67             for (LinkAddress addr : removed) retVal += addr.toString() + ",";
68             retVal += "] addedAddresses=[";
69             for (LinkAddress addr : added) retVal += addr.toString() + ",";
70             retVal += "]";
71             return retVal;
72         }
73     }
74
75     public LinkProperties() {
76         clear();
77     }
78
79     // copy constructor instead of clone
80     public LinkProperties(LinkProperties source) {
81         if (source != null) {
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());
88         }
89     }
90
91     public void setInterfaceName(String iface) {
92         mIfaceName = iface;
93     }
94
95     public String getInterfaceName() {
96         return mIfaceName;
97     }
98
99     public Collection<InetAddress> getAddresses() {
100         Collection<InetAddress> addresses = new ArrayList<InetAddress>();
101         for (LinkAddress linkAddress : mLinkAddresses) {
102             addresses.add(linkAddress.getAddress());
103         }
104         return Collections.unmodifiableCollection(addresses);
105     }
106
107     public void addLinkAddress(LinkAddress address) {
108         if (address != null) mLinkAddresses.add(address);
109     }
110
111     public Collection<LinkAddress> getLinkAddresses() {
112         return Collections.unmodifiableCollection(mLinkAddresses);
113     }
114
115     public void addDns(InetAddress dns) {
116         if (dns != null) mDnses.add(dns);
117     }
118
119     public Collection<InetAddress> getDnses() {
120         return Collections.unmodifiableCollection(mDnses);
121     }
122
123     public void addRoute(RouteInfo route) {
124         if (route != null) mRoutes.add(route);
125     }
126     public Collection<RouteInfo> getRoutes() {
127         return Collections.unmodifiableCollection(mRoutes);
128     }
129
130     public void setHttpProxy(ProxyProperties proxy) {
131         mHttpProxy = proxy;
132     }
133     public ProxyProperties getHttpProxy() {
134         return mHttpProxy;
135     }
136
137     public void clear() {
138         mIfaceName = null;
139         mLinkAddresses.clear();
140         mDnses.clear();
141         mRoutes.clear();
142         mHttpProxy = null;
143     }
144
145     /**
146      * Implement the Parcelable interface
147      * @hide
148      */
149     public int describeContents() {
150         return 0;
151     }
152
153     @Override
154     public String toString() {
155         String ifaceName = (mIfaceName == null ? "" : "InterfaceName: " + mIfaceName + " ");
156
157         String linkAddresses = "LinkAddresses: [";
158         for (LinkAddress addr : mLinkAddresses) linkAddresses += addr.toString() + ",";
159         linkAddresses += "] ";
160
161         String dns = "DnsAddresses: [";
162         for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ",";
163         dns += "] ";
164
165         String routes = "Routes: [";
166         for (RouteInfo route : mRoutes) routes += route.toString() + ",";
167         routes += "] ";
168         String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " ");
169
170         return ifaceName + linkAddresses + routes + dns + proxy;
171     }
172
173     /**
174      * Compares this {@code LinkProperties} interface name against the target
175      *
176      * @param target LinkProperties to compare.
177      * @return {@code true} if both are identical, {@code false} otherwise.
178      */
179     public boolean isIdenticalInterfaceName(LinkProperties target) {
180         return TextUtils.equals(getInterfaceName(), target.getInterfaceName());
181     }
182
183     /**
184      * Compares this {@code LinkProperties} interface name against the target
185      *
186      * @param target LinkProperties to compare.
187      * @return {@code true} if both are identical, {@code false} otherwise.
188      */
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;
194     }
195
196     /**
197      * Compares this {@code LinkProperties} DNS addresses against the target
198      *
199      * @param target LinkProperties to compare.
200      * @return {@code true} if both are identical, {@code false} otherwise.
201      */
202     public boolean isIdenticalDnses(LinkProperties target) {
203         Collection<InetAddress> targetDnses = target.getDnses();
204         return (mDnses.size() == targetDnses.size()) ?
205                     mDnses.containsAll(targetDnses) : false;
206     }
207
208     /**
209      * Compares this {@code LinkProperties} Routes against the target
210      *
211      * @param target LinkProperties to compare.
212      * @return {@code true} if both are identical, {@code false} otherwise.
213      */
214     public boolean isIdenticalRoutes(LinkProperties target) {
215         Collection<RouteInfo> targetRoutes = target.getRoutes();
216         return (mRoutes.size() == targetRoutes.size()) ?
217                     mRoutes.containsAll(targetRoutes) : false;
218     }
219
220     /**
221      * Compares this {@code LinkProperties} HttpProxy against the target
222      *
223      * @param target LinkProperties to compare.
224      * @return {@code true} if both are identical, {@code false} otherwise.
225      */
226     public boolean isIdenticalHttpProxy(LinkProperties target) {
227         return getHttpProxy() == null ? target.getHttpProxy() == null :
228                     getHttpProxy().equals(target.getHttpProxy());
229     }
230
231     @Override
232     /**
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.
236      *
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).
242      *
243      * @param obj the object to be tested for equality.
244      * @return {@code true} if both objects are equal, {@code false} otherwise.
245      */
246     public boolean equals(Object obj) {
247         if (this == obj) return true;
248
249         if (!(obj instanceof LinkProperties)) return false;
250
251         LinkProperties target = (LinkProperties) obj;
252
253         return isIdenticalInterfaceName(target) &&
254                 isIdenticalAddresses(target) &&
255                 isIdenticalDnses(target) &&
256                 isIdenticalRoutes(target) &&
257                 isIdenticalHttpProxy(target);
258     }
259
260     /**
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.
265      *
266      * @param target is a new list of addresses
267      * @return the removed and added lists.
268      */
269     public CompareAddressesResult compareAddresses(LinkProperties target) {
270         /*
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
275          * addedAddresses.
276          */
277         CompareAddressesResult result = new CompareAddressesResult();
278         result.removed = new ArrayList<LinkAddress>(mLinkAddresses);
279         result.added.clear();
280         for (LinkAddress newAddress : target.getLinkAddresses()) {
281             if (! result.removed.remove(newAddress)) {
282                 result.added.add(newAddress);
283             }
284         }
285         return result;
286     }
287
288     @Override
289     /**
290      * generate hashcode based on significant fields
291      * Equal objects must produce the same hash code, while unequal objects
292      * may have the same hash codes.
293      */
294     public int hashCode() {
295         return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
296                 + mLinkAddresses.size() * 31
297                 + mDnses.size() * 37
298                 + mRoutes.size() * 41
299                 + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode()));
300     }
301
302     /**
303      * Implement the Parcelable interface.
304      * @hide
305      */
306     public void writeToParcel(Parcel dest, int flags) {
307         dest.writeString(getInterfaceName());
308         dest.writeInt(mLinkAddresses.size());
309         for(LinkAddress linkAddress : mLinkAddresses) {
310             dest.writeParcelable(linkAddress, flags);
311         }
312
313         dest.writeInt(mDnses.size());
314         for(InetAddress d : mDnses) {
315             dest.writeByteArray(d.getAddress());
316         }
317
318         dest.writeInt(mRoutes.size());
319         for(RouteInfo route : mRoutes) {
320             dest.writeParcelable(route, flags);
321         }
322
323         if (mHttpProxy != null) {
324             dest.writeByte((byte)1);
325             dest.writeParcelable(mHttpProxy, flags);
326         } else {
327             dest.writeByte((byte)0);
328         }
329     }
330
331     /**
332      * Implement the Parcelable interface.
333      * @hide
334      */
335     public static final Creator<LinkProperties> CREATOR =
336         new Creator<LinkProperties>() {
337             public LinkProperties createFromParcel(Parcel in) {
338                 LinkProperties netProp = new LinkProperties();
339                 String iface = in.readString();
340                 if (iface != null) {
341                     try {
342                         netProp.setInterfaceName(iface);
343                     } catch (Exception e) {
344                         return null;
345                     }
346                 }
347                 int addressCount = in.readInt();
348                 for (int i=0; i<addressCount; i++) {
349                     netProp.addLinkAddress((LinkAddress)in.readParcelable(null));
350                 }
351                 addressCount = in.readInt();
352                 for (int i=0; i<addressCount; i++) {
353                     try {
354                         netProp.addDns(InetAddress.getByAddress(in.createByteArray()));
355                     } catch (UnknownHostException e) { }
356                 }
357                 addressCount = in.readInt();
358                 for (int i=0; i<addressCount; i++) {
359                     netProp.addRoute((RouteInfo)in.readParcelable(null));
360                 }
361                 if (in.readByte() == 1) {
362                     netProp.setHttpProxy((ProxyProperties)in.readParcelable(null));
363                 }
364                 return netProp;
365             }
366
367             public LinkProperties[] newArray(int size) {
368                 return new LinkProperties[size];
369             }
370         };
371 }