LinkProperties.java revision 22f407b11e11cfdb336e06e8c0d4a7ef1eafc783
147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt/*
26e80997a9a7b6a15370544edde322cd8833e9524Wink Saville * Copyright (C) 2010 The Android Open Source Project
347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt *
447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License");
547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * you may not use this file except in compliance with the License.
647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * You may obtain a copy of the License at
747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt *
847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt *      http://www.apache.org/licenses/LICENSE-2.0
947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt *
1047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * Unless required by applicable law or agreed to in writing, software
1147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS,
1247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * See the License for the specific language governing permissions and
1447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * limitations under the License.
1547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt */
1647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
1747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwaltpackage android.net;
1847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
1937e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwaltimport android.net.ProxyProperties;
2047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwaltimport android.os.Parcelable;
2147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwaltimport android.os.Parcel;
224e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wangimport android.text.TextUtils;
2347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
2447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwaltimport java.net.InetAddress;
25419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colittiimport java.net.Inet4Address;
264faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colittiimport java.net.Inet6Address;
27419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
2847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwaltimport java.net.UnknownHostException;
2947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwaltimport java.util.ArrayList;
3047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwaltimport java.util.Collection;
3137e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwaltimport java.util.Collections;
32419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colittiimport java.util.Hashtable;
3347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
3447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt/**
3537e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt * Describes the properties of a network link.
36992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt *
37992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * A link represents a connection to a network.
38992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * It may have multiple addresses and multiple gateways,
39992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * multiple dns servers but only one http proxy.
40992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt *
41992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * Because it's a single network, the dns's
42992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * are interchangeable and don't need associating with
43992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * particular addresses.  The gateways similarly don't
44992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * need associating with particular addresses.
45992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt *
46992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * A dual stack interface works fine in this model:
47992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * each address has it's own prefix length to describe
48992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * the local network.  The dns servers all return
49992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * both v4 addresses and v6 addresses regardless of the
50992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * address family of the server itself (rfc4213) and we
51992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * don't care which is used.  The gateways will be
52992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * selected based on the destination address and the
53992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt * source address has no relavence.
54419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti *
55419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti * Links can also be stacked on top of each other.
56419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti * This can be used, for example, to represent a tunnel
57419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti * interface that runs on top of a physical interface.
58419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti *
5947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt * @hide
6047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt */
6137e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwaltpublic class LinkProperties implements Parcelable {
62419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    // The interface described by the network link.
634717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt    private String mIfaceName;
64e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    private Collection<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>();
65e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    private Collection<InetAddress> mDnses = new ArrayList<InetAddress>();
668058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt    private String mDomains;
67e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    private Collection<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
6847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    private ProxyProperties mHttpProxy;
6947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
70419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    // Stores the properties of links that are "stacked" above this link.
71419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    // Indexed by interface name to allow modification and to prevent duplicates being added.
72419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    private Hashtable<String, LinkProperties> mStackedLinks =
73419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        new Hashtable<String, LinkProperties>();
74419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
750a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    public static class CompareResult<T> {
76ad55d35114237071133eb28ded93a014185d4e35Robert Greenwalt        public Collection<T> removed = new ArrayList<T>();
77ad55d35114237071133eb28ded93a014185d4e35Robert Greenwalt        public Collection<T> added = new ArrayList<T>();
78e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
79e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        @Override
80e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        public String toString() {
810a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            String retVal = "removed=[";
820a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            for (T addr : removed) retVal += addr.toString() + ",";
830a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            retVal += "] added=[";
840a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            for (T addr : added) retVal += addr.toString() + ",";
85e822225f7a01ef088ff01f7613f953d5d89945edWink Saville            retVal += "]";
86e822225f7a01ef088ff01f7613f953d5d89945edWink Saville            return retVal;
87e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        }
88e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
89e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
9037e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public LinkProperties() {
9147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        clear();
9247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
9347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
9437e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    // copy constructor instead of clone
9537e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public LinkProperties(LinkProperties source) {
96ef6c1431fa2039a4b8c604d651bb8f4dc0806581Irfan Sheriff        if (source != null) {
97ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            mIfaceName = source.getInterfaceName();
980d8acea9bb452d1fdbb3d811041f7bdb1b0ef8a3Robert Greenwalt            for (LinkAddress l : source.getLinkAddresses()) mLinkAddresses.add(l);
990d8acea9bb452d1fdbb3d811041f7bdb1b0ef8a3Robert Greenwalt            for (InetAddress i : source.getDnses()) mDnses.add(i);
1008058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt            mDomains = source.getDomains();
1010d8acea9bb452d1fdbb3d811041f7bdb1b0ef8a3Robert Greenwalt            for (RouteInfo r : source.getRoutes()) mRoutes.add(r);
102be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville            mHttpProxy = (source.getHttpProxy() == null)  ?
1038058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt                    null : new ProxyProperties(source.getHttpProxy());
104419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            for (LinkProperties l: source.mStackedLinks.values()) {
105419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                addStackedLink(l);
106419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            }
107ef6c1431fa2039a4b8c604d651bb8f4dc0806581Irfan Sheriff        }
10837e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    }
10937e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt
110ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    public void setInterfaceName(String iface) {
111ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        mIfaceName = iface;
11245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        ArrayList<RouteInfo> newRoutes = new ArrayList<RouteInfo>(mRoutes.size());
11345b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        for (RouteInfo route : mRoutes) {
11445b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            newRoutes.add(routeWithInterface(route));
11545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        }
11645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        mRoutes = newRoutes;
11747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
118ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
11937e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public String getInterfaceName() {
120ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        return mIfaceName;
12147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
12247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
1234aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti    public Collection<String> getAllInterfaceNames() {
1244aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti        Collection interfaceNames = new ArrayList<String>(mStackedLinks.size() + 1);
12555187f18505aad67f824094061af1b6d0a0ebb38Robert Greenwalt        if (mIfaceName != null) interfaceNames.add(new String(mIfaceName));
1264aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti        for (LinkProperties stacked: mStackedLinks.values()) {
1274aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti            interfaceNames.addAll(stacked.getAllInterfaceNames());
1284aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti        }
1294aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti        return interfaceNames;
1304aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti    }
1314aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti
132d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    /**
133d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Returns all the addresses on this link.
134d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     */
13537e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public Collection<InetAddress> getAddresses() {
136ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        Collection<InetAddress> addresses = new ArrayList<InetAddress>();
137ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        for (LinkAddress linkAddress : mLinkAddresses) {
138ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            addresses.add(linkAddress.getAddress());
139ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        }
140ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        return Collections.unmodifiableCollection(addresses);
141ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    }
142ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
143d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    /**
144d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Returns all the addresses on this link and all the links stacked above it.
145d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     */
146d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    public Collection<InetAddress> getAllAddresses() {
147d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        Collection<InetAddress> addresses = new ArrayList<InetAddress>();
148d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        for (LinkAddress linkAddress : mLinkAddresses) {
149d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti            addresses.add(linkAddress.getAddress());
150d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        }
151d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        for (LinkProperties stacked: mStackedLinks.values()) {
152d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti            addresses.addAll(stacked.getAllAddresses());
153d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        }
154d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        return addresses;
155d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    }
156d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti
1574faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    /**
1584faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * Adds a link address if it does not exist, or update it if it does.
1594faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @param address The {@code LinkAddress} to add.
1604faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @return true if the address was added, false if it already existed.
1614faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     */
1624faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public boolean addLinkAddress(LinkAddress address) {
1634faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // TODO: when the LinkAddress has other attributes beyond the
1644faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // address and the prefix length, update them here.
1654faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        if (address != null && !mLinkAddresses.contains(address)) {
1664faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            mLinkAddresses.add(address);
1674faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            return true;
1684faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        }
1694faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        return false;
1704faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    }
1714faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
1724faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    /**
1734faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * Removes a link address.
1744faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @param address The {@code LinkAddress} to remove.
1754faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @return true if the address was removed, false if it did not exist.
1764faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     */
1774faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public boolean removeLinkAddress(LinkAddress toRemove) {
1784faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        return mLinkAddresses.remove(toRemove);
179ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    }
180ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
181d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    /**
182d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Returns all the addresses on this link.
183d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     */
184ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    public Collection<LinkAddress> getLinkAddresses() {
185ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        return Collections.unmodifiableCollection(mLinkAddresses);
18647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
18747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
188d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    /**
189d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Returns all the addresses on this link and all the links stacked above it.
190d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     */
191d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    public Collection<LinkAddress> getAllLinkAddresses() {
192d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        Collection<LinkAddress> addresses = new ArrayList<LinkAddress>();
193d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        addresses.addAll(mLinkAddresses);
194d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        for (LinkProperties stacked: mStackedLinks.values()) {
195d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti            addresses.addAll(stacked.getAllLinkAddresses());
196d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        }
197d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        return addresses;
198d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    }
199d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti
20022f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti    /**
20122f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti     * Replaces the LinkAddresses on this link with the given collection of addresses.
20222f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti     */
20322f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti    public void setLinkAddresses(Collection<LinkAddress> addresses) {
20422f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        mLinkAddresses.clear();
20522f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        for (LinkAddress address: addresses) {
20622f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti            addLinkAddress(address);
20722f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        }
20822f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti    }
20922f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti
21037e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public void addDns(InetAddress dns) {
21104cac40ff86e175444991c07869cb85219db1019Robert Greenwalt        if (dns != null) mDnses.add(dns);
21247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
213ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
21437e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public Collection<InetAddress> getDnses() {
21537e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt        return Collections.unmodifiableCollection(mDnses);
21647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
21747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
2188058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt    public String getDomains() {
2198058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        return mDomains;
2208058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt    }
2218058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt
2228058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt    public void setDomains(String domains) {
2238058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        mDomains = domains;
2248058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt    }
2258058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt
22645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    private RouteInfo routeWithInterface(RouteInfo route) {
22745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        return new RouteInfo(
22845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            route.getDestination(),
22945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            route.getGateway(),
23045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            mIfaceName);
23145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    }
23245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
233aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public void addRoute(RouteInfo route) {
23445b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        if (route != null) {
23545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            String routeIface = route.getInterface();
23645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            if (routeIface != null && !routeIface.equals(mIfaceName)) {
2371994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti                throw new IllegalArgumentException(
23845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                   "Route added with non-matching interface: " + routeIface +
2391994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti                   " vs. " + mIfaceName);
24045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            }
24145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            mRoutes.add(routeWithInterface(route));
24245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        }
24347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
24445b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
245419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
246419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Returns all the routes on this link.
247419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
248aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public Collection<RouteInfo> getRoutes() {
249aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return Collections.unmodifiableCollection(mRoutes);
25047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
25147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
252419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
253419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Returns all the routes on this link and all the links stacked above it.
254419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
255419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    public Collection<RouteInfo> getAllRoutes() {
256419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        Collection<RouteInfo> routes = new ArrayList();
257419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        routes.addAll(mRoutes);
258419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkProperties stacked: mStackedLinks.values()) {
259419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            routes.addAll(stacked.getAllRoutes());
260419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
2616629bcd6608cccbd5997ac99bf4474c00def0431Robert Greenwalt        return routes;
262419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
263419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
26437e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public void setHttpProxy(ProxyProperties proxy) {
26547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        mHttpProxy = proxy;
26647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
26737e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public ProxyProperties getHttpProxy() {
26847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        return mHttpProxy;
26947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
27047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
271419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
272419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Adds a stacked link.
273419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
274419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * If there is already a stacked link with the same interfacename as link,
275419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * that link is replaced with link. Otherwise, link is added to the list
276419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * of stacked links. If link is null, nothing changes.
277419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
278419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * @param link The link to add.
2794faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @return true if the link was stacked, false otherwise.
280419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
2814faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public boolean addStackedLink(LinkProperties link) {
282419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        if (link != null && link.getInterfaceName() != null) {
283419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            mStackedLinks.put(link.getInterfaceName(), link);
2844faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            return true;
285419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
2864faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        return false;
287419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
288419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
289419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
290419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Removes a stacked link.
291419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
292419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * If there a stacked link with the same interfacename as link, it is
293419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * removed. Otherwise, nothing changes.
294419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
2954faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @param link The link to remove.
2964faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @return true if the link was removed, false otherwise.
297419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
2984faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public boolean removeStackedLink(LinkProperties link) {
299419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        if (link != null && link.getInterfaceName() != null) {
3004faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            LinkProperties removed = mStackedLinks.remove(link.getInterfaceName());
3014faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            return removed != null;
302419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
3034faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        return false;
304419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
305419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
306419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
307419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Returns all the links stacked on top of this link.
308419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
309419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    public Collection<LinkProperties> getStackedLinks() {
310419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        Collection<LinkProperties> stacked = new ArrayList<LinkProperties>();
311419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkProperties link : mStackedLinks.values()) {
312419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti          stacked.add(new LinkProperties(link));
313419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
314419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        return Collections.unmodifiableCollection(stacked);
315419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
316419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
31737e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public void clear() {
318ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        mIfaceName = null;
319e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        mLinkAddresses.clear();
320e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        mDnses.clear();
3218058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        mDomains = null;
322e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        mRoutes.clear();
32347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        mHttpProxy = null;
324419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        mStackedLinks.clear();
32547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
32647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
32747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    /**
32847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     * Implement the Parcelable interface
32947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     * @hide
33047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     */
33147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    public int describeContents() {
33247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        return 0;
33347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
33447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
3351f6408a96c757b3001c553f8f34ef0bda00a224dWink Saville    @Override
33637e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public String toString() {
337ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        String ifaceName = (mIfaceName == null ? "" : "InterfaceName: " + mIfaceName + " ");
33847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
339ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        String linkAddresses = "LinkAddresses: [";
3404e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        for (LinkAddress addr : mLinkAddresses) linkAddresses += addr.toString() + ",";
341ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        linkAddresses += "] ";
34247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
34347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        String dns = "DnsAddresses: [";
3441f6408a96c757b3001c553f8f34ef0bda00a224dWink Saville        for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ",";
34547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        dns += "] ";
34647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
3478058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        String domainName = "Domains: " + mDomains;
3488058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt
3498058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        String routes = " Routes: [";
350aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        for (RouteInfo route : mRoutes) routes += route.toString() + ",";
351aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        routes += "] ";
35247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " ");
35347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
354419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        String stacked = "";
355419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        if (mStackedLinks.values().size() > 0) {
356419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            stacked += " Stacked: [";
357419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            for (LinkProperties link: mStackedLinks.values()) {
358419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                stacked += " [" + link.toString() + " ],";
359419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            }
360419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            stacked += "] ";
361419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
36215bc62fe205b755582845829821373985efc60afWink Saville        return "{" + ifaceName + linkAddresses + routes + dns + domainName + proxy + stacked + "}";
363419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
364419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
365419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
366419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Returns true if this link has an IPv4 address.
367419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
368419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
369419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
370419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    public boolean hasIPv4Address() {
371419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkAddress address : mLinkAddresses) {
372419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti          if (address.getAddress() instanceof Inet4Address) {
373419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            return true;
374419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti          }
375419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
376419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        return false;
37747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
37847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
379e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
3804faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * Returns true if this link has an IPv6 address.
3814faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     *
3824faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @return {@code true} if there is an IPv6 address, {@code false} otherwise.
3834faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     */
3844faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public boolean hasIPv6Address() {
3854faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        for (LinkAddress address : mLinkAddresses) {
3864faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti          if (address.getAddress() instanceof Inet6Address) {
3874faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            return true;
3884faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti          }
3894faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        }
3904faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        return false;
3914faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    }
3924faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
3934faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    /**
394e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * Compares this {@code LinkProperties} interface name against the target
395e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
396e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
397e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
398e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
399e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalInterfaceName(LinkProperties target) {
400e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return TextUtils.equals(getInterfaceName(), target.getInterfaceName());
401e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
402e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
403e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
4044717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt     * Compares this {@code LinkProperties} interface addresses against the target
405e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
406e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
407e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
408e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
409e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalAddresses(LinkProperties target) {
410e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        Collection<InetAddress> targetAddresses = target.getAddresses();
411e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        Collection<InetAddress> sourceAddresses = getAddresses();
412e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return (sourceAddresses.size() == targetAddresses.size()) ?
413e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                    sourceAddresses.containsAll(targetAddresses) : false;
414e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
415e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
416e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
417e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * Compares this {@code LinkProperties} DNS addresses against the target
418e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
419e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
420e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
421e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
422e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalDnses(LinkProperties target) {
423e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        Collection<InetAddress> targetDnses = target.getDnses();
4248058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        String targetDomains = target.getDomains();
4258058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        if (mDomains == null) {
4268058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt            if (targetDomains != null) return false;
4278058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        } else {
4288058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt            if (mDomains.equals(targetDomains) == false) return false;
4298058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        }
430e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return (mDnses.size() == targetDnses.size()) ?
431e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                    mDnses.containsAll(targetDnses) : false;
432e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
433e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
434e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
435e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * Compares this {@code LinkProperties} Routes against the target
436e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
437e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
438e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
439e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
440e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalRoutes(LinkProperties target) {
441e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        Collection<RouteInfo> targetRoutes = target.getRoutes();
442e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return (mRoutes.size() == targetRoutes.size()) ?
443e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                    mRoutes.containsAll(targetRoutes) : false;
444e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
445e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
446e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
447e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * Compares this {@code LinkProperties} HttpProxy against the target
448e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
449e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
450e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
451e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
452e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalHttpProxy(LinkProperties target) {
453e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return getHttpProxy() == null ? target.getHttpProxy() == null :
454e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                    getHttpProxy().equals(target.getHttpProxy());
455e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
4564e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
457419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
458419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Compares this {@code LinkProperties} stacked links against the target
459419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
460419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * @param target LinkProperties to compare.
461419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * @return {@code true} if both are identical, {@code false} otherwise.
462419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
463419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    public boolean isIdenticalStackedLinks(LinkProperties target) {
464213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        if (!mStackedLinks.keySet().equals(target.mStackedLinks.keySet())) {
465419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            return false;
466419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
467419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkProperties stacked : mStackedLinks.values()) {
468419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            // Hashtable values can never be null.
469419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            String iface = stacked.getInterfaceName();
470419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            if (!stacked.equals(target.mStackedLinks.get(iface))) {
471419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                return false;
472419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            }
473419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
474419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        return true;
475419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
476419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
4774e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    @Override
4784e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    /**
4794e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * Compares this {@code LinkProperties} instance against the target
4804e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
4814e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * all their fields are equal in values.
4824e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     *
4834e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * For collection fields, such as mDnses, containsAll() is used to check
4844e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * if two collections contains the same elements, independent of order.
4854e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * There are two thoughts regarding containsAll()
4864e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal.
4874e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * 2. Worst case performance is O(n^2).
4884e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     *
489419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * This method does not check that stacked interfaces are equal, because
490419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * stacked interfaces are not so much a property of the link as a
491419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * description of connections between links.
492419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
4934e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * @param obj the object to be tested for equality.
4944e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * @return {@code true} if both objects are equal, {@code false} otherwise.
4954e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     */
4964e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    public boolean equals(Object obj) {
4974e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        if (this == obj) return true;
4984e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
4994e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        if (!(obj instanceof LinkProperties)) return false;
5004e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
5014e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        LinkProperties target = (LinkProperties) obj;
5024e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
503e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return isIdenticalInterfaceName(target) &&
504e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                isIdenticalAddresses(target) &&
505e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                isIdenticalDnses(target) &&
506e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                isIdenticalRoutes(target) &&
507419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                isIdenticalHttpProxy(target) &&
508419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                isIdenticalStackedLinks(target);
509e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
5104e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
511e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
512d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Compares the addresses in this LinkProperties with another
513d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * LinkProperties, examining only addresses on the base link.
514e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
515d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @param target a LinkProperties with the new list of addresses
516d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @return the differences between the addresses.
517e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
5180a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    public CompareResult<LinkAddress> compareAddresses(LinkProperties target) {
519e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        /*
520e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * Duplicate the LinkAddresses into removed, we will be removing
521e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * address which are common between mLinkAddresses and target
522e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * leaving the addresses that are different. And address which
523e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * are in target but not in mLinkAddresses are placed in the
524e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * addedAddresses.
525e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         */
5260a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        CompareResult<LinkAddress> result = new CompareResult<LinkAddress>();
527e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        result.removed = new ArrayList<LinkAddress>(mLinkAddresses);
528e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        result.added.clear();
5290a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        if (target != null) {
5300a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            for (LinkAddress newAddress : target.getLinkAddresses()) {
5310a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                if (! result.removed.remove(newAddress)) {
5320a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                    result.added.add(newAddress);
5330a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                }
534e822225f7a01ef088ff01f7613f953d5d89945edWink Saville            }
535e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        }
536e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return result;
5374e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
5384e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
5390a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    /**
540d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Compares the DNS addresses in this LinkProperties with another
541d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * LinkProperties, examining only DNS addresses on the base link.
5420a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt     *
543d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @param target a LinkProperties with the new list of dns addresses
544d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @return the differences between the DNS addresses.
5450a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt     */
5460a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    public CompareResult<InetAddress> compareDnses(LinkProperties target) {
5470a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        /*
5480a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * Duplicate the InetAddresses into removed, we will be removing
5490a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * dns address which are common between mDnses and target
5500a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * leaving the addresses that are different. And dns address which
5510a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * are in target but not in mDnses are placed in the
5520a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * addedAddresses.
5530a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         */
5540a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        CompareResult<InetAddress> result = new CompareResult<InetAddress>();
5550a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
5560a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        result.removed = new ArrayList<InetAddress>(mDnses);
5570a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        result.added.clear();
5580a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        if (target != null) {
5590a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            for (InetAddress newAddress : target.getDnses()) {
5600a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                if (! result.removed.remove(newAddress)) {
5610a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                    result.added.add(newAddress);
5620a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                }
5630a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            }
5640a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        }
5650a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        return result;
5660a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    }
5670a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
5680a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    /**
569d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Compares all routes in this LinkProperties with another LinkProperties,
570d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * examining both the the base link and all stacked links.
5710a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt     *
572d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @param target a LinkProperties with the new list of routes
573d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @return the differences between the routes.
5740a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt     */
575d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    public CompareResult<RouteInfo> compareAllRoutes(LinkProperties target) {
5760a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        /*
5770a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * Duplicate the RouteInfos into removed, we will be removing
5781994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti         * routes which are common between mRoutes and target
5790a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * leaving the routes that are different. And route address which
5800a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * are in target but not in mRoutes are placed in added.
5810a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         */
5820a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        CompareResult<RouteInfo> result = new CompareResult<RouteInfo>();
5830a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
584419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        result.removed = getAllRoutes();
5850a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        result.added.clear();
5860a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        if (target != null) {
587419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            for (RouteInfo r : target.getAllRoutes()) {
5880a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                if (! result.removed.remove(r)) {
5890a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                    result.added.add(r);
5900a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                }
5910a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            }
5920a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        }
5930a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        return result;
5940a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    }
5950a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
5960a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
5974e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    @Override
5984e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    /**
5994e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * generate hashcode based on significant fields
6004e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * Equal objects must produce the same hash code, while unequal objects
6014e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * may have the same hash codes.
6024e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     */
6034e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    public int hashCode() {
6044e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
6054e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang                + mLinkAddresses.size() * 31
6064e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang                + mDnses.size() * 37
6078058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt                + ((null == mDomains) ? 0 : mDomains.hashCode())
608aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                + mRoutes.size() * 41
609419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode())
610419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                + mStackedLinks.hashCode() * 47);
6114e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
6124e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
61347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    /**
61447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     * Implement the Parcelable interface.
61547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     */
61637e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public void writeToParcel(Parcel dest, int flags) {
61747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        dest.writeString(getInterfaceName());
618ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        dest.writeInt(mLinkAddresses.size());
619ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        for(LinkAddress linkAddress : mLinkAddresses) {
620ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            dest.writeParcelable(linkAddress, flags);
62147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        }
622ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
62347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        dest.writeInt(mDnses.size());
62447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        for(InetAddress d : mDnses) {
62547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            dest.writeByteArray(d.getAddress());
62647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        }
6278058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        dest.writeString(mDomains);
628992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt
629aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        dest.writeInt(mRoutes.size());
630aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        for(RouteInfo route : mRoutes) {
631aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeParcelable(route, flags);
63247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        }
633992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt
63447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        if (mHttpProxy != null) {
63547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            dest.writeByte((byte)1);
63647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            dest.writeParcelable(mHttpProxy, flags);
63747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        } else {
63847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            dest.writeByte((byte)0);
63947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        }
640419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        ArrayList<LinkProperties> stackedLinks = new ArrayList(mStackedLinks.values());
641419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        dest.writeList(stackedLinks);
64247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
64347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
64447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    /**
64547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     * Implement the Parcelable interface.
64647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     */
64737e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public static final Creator<LinkProperties> CREATOR =
64837e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt        new Creator<LinkProperties>() {
64937e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt            public LinkProperties createFromParcel(Parcel in) {
65037e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt                LinkProperties netProp = new LinkProperties();
6514717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt
65247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                String iface = in.readString();
65347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                if (iface != null) {
6544717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt                    netProp.setInterfaceName(iface);
65547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
65647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                int addressCount = in.readInt();
65747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                for (int i=0; i<addressCount; i++) {
658ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff                    netProp.addLinkAddress((LinkAddress)in.readParcelable(null));
65947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
66047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                addressCount = in.readInt();
66147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                for (int i=0; i<addressCount; i++) {
66247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                    try {
6631cf56ab9c68334d9124c52bcede06aaa0b17c730Irfan Sheriff                        netProp.addDns(InetAddress.getByAddress(in.createByteArray()));
66447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                    } catch (UnknownHostException e) { }
66547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
6668058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt                netProp.setDomains(in.readString());
667992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt                addressCount = in.readInt();
668992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt                for (int i=0; i<addressCount; i++) {
669aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                    netProp.addRoute((RouteInfo)in.readParcelable(null));
67047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
67147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                if (in.readByte() == 1) {
67247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                    netProp.setHttpProxy((ProxyProperties)in.readParcelable(null));
67347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
674419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                ArrayList<LinkProperties> stackedLinks = new ArrayList<LinkProperties>();
675419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                in.readList(stackedLinks, LinkProperties.class.getClassLoader());
676419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                for (LinkProperties stackedLink: stackedLinks) {
677419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                    netProp.addStackedLink(stackedLink);
678419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                }
67947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                return netProp;
68047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            }
68147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
68237e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt            public LinkProperties[] newArray(int size) {
68337e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt                return new LinkProperties[size];
68447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            }
68547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        };
68647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt}
687