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