LinkProperties.java revision 992f25257938ecc0378514f21c6e6e6375272976
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
19207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monkimport android.net.ProxyInfo;
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;
6464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti    private ArrayList<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>();
6564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti    private ArrayList<InetAddress> mDnses = new ArrayList<InetAddress>();
668058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt    private String mDomains;
6764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti    private ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
68207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk    private ProxyInfo mHttpProxy;
699d9b74a900696191048aa97cc3c854072640428bsy.yun    private int mMtu;
7047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
71419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    // Stores the properties of links that are "stacked" above this link.
72419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    // Indexed by interface name to allow modification and to prevent duplicates being added.
73419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    private Hashtable<String, LinkProperties> mStackedLinks =
74419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        new Hashtable<String, LinkProperties>();
75419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
760a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    public static class CompareResult<T> {
77ad55d35114237071133eb28ded93a014185d4e35Robert Greenwalt        public Collection<T> removed = new ArrayList<T>();
78ad55d35114237071133eb28ded93a014185d4e35Robert Greenwalt        public Collection<T> added = new ArrayList<T>();
79e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
80e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        @Override
81e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        public String toString() {
820a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            String retVal = "removed=[";
830a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            for (T addr : removed) retVal += addr.toString() + ",";
840a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            retVal += "] added=[";
850a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            for (T addr : added) retVal += addr.toString() + ",";
86e822225f7a01ef088ff01f7613f953d5d89945edWink Saville            retVal += "]";
87e822225f7a01ef088ff01f7613f953d5d89945edWink Saville            return retVal;
88e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        }
89e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
90e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
9137e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public LinkProperties() {
9247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        clear();
9347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
9447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
9537e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    // copy constructor instead of clone
9637e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public LinkProperties(LinkProperties source) {
97ef6c1431fa2039a4b8c604d651bb8f4dc0806581Irfan Sheriff        if (source != null) {
98ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            mIfaceName = source.getInterfaceName();
990d8acea9bb452d1fdbb3d811041f7bdb1b0ef8a3Robert Greenwalt            for (LinkAddress l : source.getLinkAddresses()) mLinkAddresses.add(l);
1000d8acea9bb452d1fdbb3d811041f7bdb1b0ef8a3Robert Greenwalt            for (InetAddress i : source.getDnses()) mDnses.add(i);
1018058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt            mDomains = source.getDomains();
1020d8acea9bb452d1fdbb3d811041f7bdb1b0ef8a3Robert Greenwalt            for (RouteInfo r : source.getRoutes()) mRoutes.add(r);
103be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville            mHttpProxy = (source.getHttpProxy() == null)  ?
104207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk                    null : new ProxyInfo(source.getHttpProxy());
105419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            for (LinkProperties l: source.mStackedLinks.values()) {
106419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                addStackedLink(l);
107419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            }
1089d9b74a900696191048aa97cc3c854072640428bsy.yun            setMtu(source.getMtu());
109ef6c1431fa2039a4b8c604d651bb8f4dc0806581Irfan Sheriff        }
11037e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    }
11137e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt
112ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    public void setInterfaceName(String iface) {
113ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        mIfaceName = iface;
11445b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        ArrayList<RouteInfo> newRoutes = new ArrayList<RouteInfo>(mRoutes.size());
11545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        for (RouteInfo route : mRoutes) {
11645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            newRoutes.add(routeWithInterface(route));
11745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        }
11845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        mRoutes = newRoutes;
11947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
120ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
12137e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public String getInterfaceName() {
122ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        return mIfaceName;
12347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
12447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
1254aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti    public Collection<String> getAllInterfaceNames() {
1264aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti        Collection interfaceNames = new ArrayList<String>(mStackedLinks.size() + 1);
12755187f18505aad67f824094061af1b6d0a0ebb38Robert Greenwalt        if (mIfaceName != null) interfaceNames.add(new String(mIfaceName));
1284aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti        for (LinkProperties stacked: mStackedLinks.values()) {
1294aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti            interfaceNames.addAll(stacked.getAllInterfaceNames());
1304aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti        }
1314aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti        return interfaceNames;
1324aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti    }
1334aa9bcf414282e4bdd10900832baaeaa349bda50Lorenzo Colitti
134d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    /**
135d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Returns all the addresses on this link.
136d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     */
13737e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public Collection<InetAddress> getAddresses() {
138ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        Collection<InetAddress> addresses = new ArrayList<InetAddress>();
139ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        for (LinkAddress linkAddress : mLinkAddresses) {
140ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            addresses.add(linkAddress.getAddress());
141ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        }
142ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        return Collections.unmodifiableCollection(addresses);
143ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    }
144ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
145d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    /**
146d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Returns all the addresses on this link and all the links stacked above it.
147d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     */
148d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    public Collection<InetAddress> getAllAddresses() {
149d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        Collection<InetAddress> addresses = new ArrayList<InetAddress>();
150d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        for (LinkAddress linkAddress : mLinkAddresses) {
151d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti            addresses.add(linkAddress.getAddress());
152d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        }
153d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        for (LinkProperties stacked: mStackedLinks.values()) {
154d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti            addresses.addAll(stacked.getAllAddresses());
155d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        }
156d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        return addresses;
157d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    }
158d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti
15964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti    private int findLinkAddressIndex(LinkAddress address) {
16064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        for (int i = 0; i < mLinkAddresses.size(); i++) {
16164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            if (mLinkAddresses.get(i).isSameAddressAs(address)) {
16264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti                return i;
16364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            }
16464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        }
16564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        return -1;
16664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti    }
16764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti
1684faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    /**
16964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti     * Adds a link address if it does not exist, or updates it if it does.
1704faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @param address The {@code LinkAddress} to add.
17164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti     * @return true if {@code address} was added or updated, false otherwise.
1724faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     */
1734faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public boolean addLinkAddress(LinkAddress address) {
17464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        if (address == null) {
17564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            return false;
17664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        }
17764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        int i = findLinkAddressIndex(address);
17864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        if (i < 0) {
17964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            // Address was not present. Add it.
1804faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            mLinkAddresses.add(address);
1814faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            return true;
18264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        } else if (mLinkAddresses.get(i).equals(address)) {
18364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            // Address was present and has same properties. Do nothing.
18464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            return false;
18564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        } else {
18664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            // Address was present and has different properties. Update it.
18764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            mLinkAddresses.set(i, address);
18864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            return true;
1894faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        }
1904faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    }
1914faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
1924faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    /**
19364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti     * Removes a link address. Specifically, removes the link address, if any, for which
19464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti     * {@code isSameAddressAs(toRemove)} returns true.
19564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti     * @param address A {@code LinkAddress} specifying the address to remove.
1964faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @return true if the address was removed, false if it did not exist.
1974faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     */
1984faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public boolean removeLinkAddress(LinkAddress toRemove) {
19964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        int i = findLinkAddressIndex(toRemove);
20064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        if (i >= 0) {
20164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            mLinkAddresses.remove(i);
20264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti            return true;
20364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        }
20464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        return false;
205ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    }
206ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
207d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    /**
208d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Returns all the addresses on this link.
209d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     */
210ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff    public Collection<LinkAddress> getLinkAddresses() {
211ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        return Collections.unmodifiableCollection(mLinkAddresses);
21247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
21347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
214d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    /**
215d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Returns all the addresses on this link and all the links stacked above it.
216d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     */
217d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    public Collection<LinkAddress> getAllLinkAddresses() {
218d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        Collection<LinkAddress> addresses = new ArrayList<LinkAddress>();
219d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        addresses.addAll(mLinkAddresses);
220d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        for (LinkProperties stacked: mStackedLinks.values()) {
221d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti            addresses.addAll(stacked.getAllLinkAddresses());
222d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        }
223d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        return addresses;
224d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    }
225d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti
22622f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti    /**
22722f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti     * Replaces the LinkAddresses on this link with the given collection of addresses.
22822f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti     */
22922f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti    public void setLinkAddresses(Collection<LinkAddress> addresses) {
23022f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        mLinkAddresses.clear();
23122f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        for (LinkAddress address: addresses) {
23222f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti            addLinkAddress(address);
23322f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        }
23422f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti    }
23522f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti
23637e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public void addDns(InetAddress dns) {
23704cac40ff86e175444991c07869cb85219db1019Robert Greenwalt        if (dns != null) mDnses.add(dns);
23847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
239ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
24037e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public Collection<InetAddress> getDnses() {
24137e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt        return Collections.unmodifiableCollection(mDnses);
24247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
24347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
2448058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt    public String getDomains() {
2458058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        return mDomains;
2468058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt    }
2478058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt
2488058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt    public void setDomains(String domains) {
2498058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        mDomains = domains;
2508058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt    }
2518058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt
2529d9b74a900696191048aa97cc3c854072640428bsy.yun    public void setMtu(int mtu) {
2539d9b74a900696191048aa97cc3c854072640428bsy.yun        mMtu = mtu;
2549d9b74a900696191048aa97cc3c854072640428bsy.yun    }
2559d9b74a900696191048aa97cc3c854072640428bsy.yun
2569d9b74a900696191048aa97cc3c854072640428bsy.yun    public int getMtu() {
2579d9b74a900696191048aa97cc3c854072640428bsy.yun        return mMtu;
2589d9b74a900696191048aa97cc3c854072640428bsy.yun    }
2599d9b74a900696191048aa97cc3c854072640428bsy.yun
26045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    private RouteInfo routeWithInterface(RouteInfo route) {
26145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        return new RouteInfo(
26245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            route.getDestination(),
26345b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            route.getGateway(),
26445b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            mIfaceName);
26545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    }
26645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
267aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public void addRoute(RouteInfo route) {
26845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        if (route != null) {
26945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            String routeIface = route.getInterface();
27045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            if (routeIface != null && !routeIface.equals(mIfaceName)) {
2711994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti                throw new IllegalArgumentException(
27245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                   "Route added with non-matching interface: " + routeIface +
2731994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti                   " vs. " + mIfaceName);
27445b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            }
27545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            mRoutes.add(routeWithInterface(route));
27645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        }
27747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
27845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
279419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
280419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Returns all the routes on this link.
281419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
282aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public Collection<RouteInfo> getRoutes() {
283aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return Collections.unmodifiableCollection(mRoutes);
28447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
28547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
286419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
287419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Returns all the routes on this link and all the links stacked above it.
288419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
289419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    public Collection<RouteInfo> getAllRoutes() {
290419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        Collection<RouteInfo> routes = new ArrayList();
291419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        routes.addAll(mRoutes);
292419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkProperties stacked: mStackedLinks.values()) {
293419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            routes.addAll(stacked.getAllRoutes());
294419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
2956629bcd6608cccbd5997ac99bf4474c00def0431Robert Greenwalt        return routes;
296419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
297419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
298207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk    public void setHttpProxy(ProxyInfo proxy) {
29947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        mHttpProxy = proxy;
30047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
301207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk    public ProxyInfo getHttpProxy() {
30247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        return mHttpProxy;
30347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
30447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
305419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
306419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Adds a stacked link.
307419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
308419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * If there is already a stacked link with the same interfacename as link,
309419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * that link is replaced with link. Otherwise, link is added to the list
310419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * of stacked links. If link is null, nothing changes.
311419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
312419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * @param link The link to add.
3134faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @return true if the link was stacked, false otherwise.
314419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
3154faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public boolean addStackedLink(LinkProperties link) {
316419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        if (link != null && link.getInterfaceName() != null) {
317419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            mStackedLinks.put(link.getInterfaceName(), link);
3184faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            return true;
319419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
3204faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        return false;
321419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
322419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
323419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
324419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Removes a stacked link.
325419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
326419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * If there a stacked link with the same interfacename as link, it is
327419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * removed. Otherwise, nothing changes.
328419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
3294faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @param link The link to remove.
3304faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @return true if the link was removed, false otherwise.
331419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
3324faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public boolean removeStackedLink(LinkProperties link) {
333419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        if (link != null && link.getInterfaceName() != null) {
3344faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            LinkProperties removed = mStackedLinks.remove(link.getInterfaceName());
3354faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            return removed != null;
336419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
3374faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        return false;
338419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
339419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
340419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
341419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Returns all the links stacked on top of this link.
342419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
343419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    public Collection<LinkProperties> getStackedLinks() {
344419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        Collection<LinkProperties> stacked = new ArrayList<LinkProperties>();
345419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkProperties link : mStackedLinks.values()) {
346419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti          stacked.add(new LinkProperties(link));
347419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
348419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        return Collections.unmodifiableCollection(stacked);
349419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
350419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
35137e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public void clear() {
352ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        mIfaceName = null;
353e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        mLinkAddresses.clear();
354e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        mDnses.clear();
3558058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        mDomains = null;
356e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        mRoutes.clear();
35747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        mHttpProxy = null;
358419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        mStackedLinks.clear();
3599d9b74a900696191048aa97cc3c854072640428bsy.yun        mMtu = 0;
36047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
36147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
36247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    /**
36347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     * Implement the Parcelable interface
36447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     * @hide
36547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     */
36647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    public int describeContents() {
36747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        return 0;
36847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
36947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
3701f6408a96c757b3001c553f8f34ef0bda00a224dWink Saville    @Override
37137e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public String toString() {
372ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        String ifaceName = (mIfaceName == null ? "" : "InterfaceName: " + mIfaceName + " ");
37347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
374ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        String linkAddresses = "LinkAddresses: [";
3754e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        for (LinkAddress addr : mLinkAddresses) linkAddresses += addr.toString() + ",";
376ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        linkAddresses += "] ";
37747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
37847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        String dns = "DnsAddresses: [";
3791f6408a96c757b3001c553f8f34ef0bda00a224dWink Saville        for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ",";
38047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        dns += "] ";
38147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
3828058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        String domainName = "Domains: " + mDomains;
3838058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt
3849d9b74a900696191048aa97cc3c854072640428bsy.yun        String mtu = "MTU: " + mMtu;
3859d9b74a900696191048aa97cc3c854072640428bsy.yun
3868058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        String routes = " Routes: [";
387aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        for (RouteInfo route : mRoutes) routes += route.toString() + ",";
388aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        routes += "] ";
38947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " ");
39047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
391419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        String stacked = "";
392419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        if (mStackedLinks.values().size() > 0) {
393419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            stacked += " Stacked: [";
394419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            for (LinkProperties link: mStackedLinks.values()) {
395419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                stacked += " [" + link.toString() + " ],";
396419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            }
397419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            stacked += "] ";
398419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
3999d9b74a900696191048aa97cc3c854072640428bsy.yun        return "{" + ifaceName + linkAddresses + routes + dns + domainName + mtu
4009d9b74a900696191048aa97cc3c854072640428bsy.yun            + proxy + stacked + "}";
401419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
402419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
403419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
404419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Returns true if this link has an IPv4 address.
405419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
406419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
407419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
408419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    public boolean hasIPv4Address() {
409419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkAddress address : mLinkAddresses) {
410419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti          if (address.getAddress() instanceof Inet4Address) {
411419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            return true;
412419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti          }
413419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
414419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        return false;
41547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
41647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
417e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
4184faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * Returns true if this link has an IPv6 address.
4194faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     *
4204faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     * @return {@code true} if there is an IPv6 address, {@code false} otherwise.
4214faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti     */
4224faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public boolean hasIPv6Address() {
4234faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        for (LinkAddress address : mLinkAddresses) {
4244faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti          if (address.getAddress() instanceof Inet6Address) {
4254faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti            return true;
4264faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti          }
4274faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        }
4284faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        return false;
4294faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    }
4304faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
4314faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    /**
432e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * Compares this {@code LinkProperties} interface name against the target
433e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
434e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
435e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
436e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
437e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalInterfaceName(LinkProperties target) {
438e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return TextUtils.equals(getInterfaceName(), target.getInterfaceName());
439e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
440e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
441e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
4424717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt     * Compares this {@code LinkProperties} interface addresses against the target
443e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
444e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
445e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
446e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
447e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalAddresses(LinkProperties target) {
448e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        Collection<InetAddress> targetAddresses = target.getAddresses();
449e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        Collection<InetAddress> sourceAddresses = getAddresses();
450e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return (sourceAddresses.size() == targetAddresses.size()) ?
451e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                    sourceAddresses.containsAll(targetAddresses) : false;
452e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
453e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
454e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
455e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * Compares this {@code LinkProperties} DNS addresses against the target
456e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
457e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
458e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
459e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
460e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalDnses(LinkProperties target) {
461e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        Collection<InetAddress> targetDnses = target.getDnses();
4628058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        String targetDomains = target.getDomains();
4638058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        if (mDomains == null) {
4648058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt            if (targetDomains != null) return false;
4658058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        } else {
4668058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt            if (mDomains.equals(targetDomains) == false) return false;
4678058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        }
468e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return (mDnses.size() == targetDnses.size()) ?
469e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                    mDnses.containsAll(targetDnses) : false;
470e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
471e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
472e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
473e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * Compares this {@code LinkProperties} Routes against the target
474e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
475e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
476e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
477e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
478e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalRoutes(LinkProperties target) {
479e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        Collection<RouteInfo> targetRoutes = target.getRoutes();
480e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return (mRoutes.size() == targetRoutes.size()) ?
481e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                    mRoutes.containsAll(targetRoutes) : false;
482e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
483e822225f7a01ef088ff01f7613f953d5d89945edWink Saville
484e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
485e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * Compares this {@code LinkProperties} HttpProxy against the target
486e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
487e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @param target LinkProperties to compare.
488e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     * @return {@code true} if both are identical, {@code false} otherwise.
489e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
490e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    public boolean isIdenticalHttpProxy(LinkProperties target) {
491e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return getHttpProxy() == null ? target.getHttpProxy() == null :
492e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                    getHttpProxy().equals(target.getHttpProxy());
493e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
4944e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
495419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    /**
496419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * Compares this {@code LinkProperties} stacked links against the target
497419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
498419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * @param target LinkProperties to compare.
499419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * @return {@code true} if both are identical, {@code false} otherwise.
500419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     */
501419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    public boolean isIdenticalStackedLinks(LinkProperties target) {
502213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        if (!mStackedLinks.keySet().equals(target.mStackedLinks.keySet())) {
503419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            return false;
504419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
505419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkProperties stacked : mStackedLinks.values()) {
506419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            // Hashtable values can never be null.
507419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            String iface = stacked.getInterfaceName();
508419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            if (!stacked.equals(target.mStackedLinks.get(iface))) {
509419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                return false;
510419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            }
511419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
512419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        return true;
513419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    }
514419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
5159d9b74a900696191048aa97cc3c854072640428bsy.yun    /**
5169d9b74a900696191048aa97cc3c854072640428bsy.yun     * Compares this {@code LinkProperties} MTU against the target
5179d9b74a900696191048aa97cc3c854072640428bsy.yun     *
518d57de6afb8981dc1663d41a842ab7cdae93427a1Ying Wang     * @param target LinkProperties to compare.
5199d9b74a900696191048aa97cc3c854072640428bsy.yun     * @return {@code true} if both are identical, {@code false} otherwise.
5209d9b74a900696191048aa97cc3c854072640428bsy.yun     */
5219d9b74a900696191048aa97cc3c854072640428bsy.yun    public boolean isIdenticalMtu(LinkProperties target) {
5229d9b74a900696191048aa97cc3c854072640428bsy.yun        return getMtu() == target.getMtu();
5239d9b74a900696191048aa97cc3c854072640428bsy.yun    }
5249d9b74a900696191048aa97cc3c854072640428bsy.yun
5254e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    @Override
5264e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    /**
5274e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * Compares this {@code LinkProperties} instance against the target
5284e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
5294e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * all their fields are equal in values.
5304e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     *
5314e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * For collection fields, such as mDnses, containsAll() is used to check
5324e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * if two collections contains the same elements, independent of order.
5334e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * There are two thoughts regarding containsAll()
5344e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal.
5354e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * 2. Worst case performance is O(n^2).
5364e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     *
537419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * This method does not check that stacked interfaces are equal, because
538419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * stacked interfaces are not so much a property of the link as a
539419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     * description of connections between links.
540419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti     *
5414e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * @param obj the object to be tested for equality.
5424e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * @return {@code true} if both objects are equal, {@code false} otherwise.
5434e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     */
5444e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    public boolean equals(Object obj) {
5454e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        if (this == obj) return true;
5464e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
5474e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        if (!(obj instanceof LinkProperties)) return false;
5484e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
5494e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        LinkProperties target = (LinkProperties) obj;
5504e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
551e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return isIdenticalInterfaceName(target) &&
552e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                isIdenticalAddresses(target) &&
553e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                isIdenticalDnses(target) &&
554e822225f7a01ef088ff01f7613f953d5d89945edWink Saville                isIdenticalRoutes(target) &&
555419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                isIdenticalHttpProxy(target) &&
5569d9b74a900696191048aa97cc3c854072640428bsy.yun                isIdenticalStackedLinks(target) &&
5579d9b74a900696191048aa97cc3c854072640428bsy.yun                isIdenticalMtu(target);
558e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    }
5594e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
560e822225f7a01ef088ff01f7613f953d5d89945edWink Saville    /**
561d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Compares the addresses in this LinkProperties with another
562d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * LinkProperties, examining only addresses on the base link.
563e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     *
564d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @param target a LinkProperties with the new list of addresses
565d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @return the differences between the addresses.
566e822225f7a01ef088ff01f7613f953d5d89945edWink Saville     */
5670a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    public CompareResult<LinkAddress> compareAddresses(LinkProperties target) {
568e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        /*
569e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * Duplicate the LinkAddresses into removed, we will be removing
570e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * address which are common between mLinkAddresses and target
571e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * leaving the addresses that are different. And address which
572e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * are in target but not in mLinkAddresses are placed in the
573e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         * addedAddresses.
574e822225f7a01ef088ff01f7613f953d5d89945edWink Saville         */
5750a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        CompareResult<LinkAddress> result = new CompareResult<LinkAddress>();
576e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        result.removed = new ArrayList<LinkAddress>(mLinkAddresses);
577e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        result.added.clear();
5780a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        if (target != null) {
5790a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            for (LinkAddress newAddress : target.getLinkAddresses()) {
5800a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                if (! result.removed.remove(newAddress)) {
5810a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                    result.added.add(newAddress);
5820a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                }
583e822225f7a01ef088ff01f7613f953d5d89945edWink Saville            }
584e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        }
585e822225f7a01ef088ff01f7613f953d5d89945edWink Saville        return result;
5864e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
5874e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
5880a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    /**
589d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Compares the DNS addresses in this LinkProperties with another
590d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * LinkProperties, examining only DNS addresses on the base link.
5910a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt     *
592d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @param target a LinkProperties with the new list of dns addresses
593d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @return the differences between the DNS addresses.
5940a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt     */
5950a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    public CompareResult<InetAddress> compareDnses(LinkProperties target) {
5960a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        /*
5970a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * Duplicate the InetAddresses into removed, we will be removing
5980a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * dns address which are common between mDnses and target
5990a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * leaving the addresses that are different. And dns address which
6000a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * are in target but not in mDnses are placed in the
6010a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * addedAddresses.
6020a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         */
6030a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        CompareResult<InetAddress> result = new CompareResult<InetAddress>();
6040a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
6050a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        result.removed = new ArrayList<InetAddress>(mDnses);
6060a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        result.added.clear();
6070a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        if (target != null) {
6080a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            for (InetAddress newAddress : target.getDnses()) {
6090a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                if (! result.removed.remove(newAddress)) {
6100a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                    result.added.add(newAddress);
6110a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                }
6120a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            }
6130a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        }
6140a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        return result;
6150a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    }
6160a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
6170a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    /**
618d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * Compares all routes in this LinkProperties with another LinkProperties,
619d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * examining both the the base link and all stacked links.
6200a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt     *
621d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @param target a LinkProperties with the new list of routes
622d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti     * @return the differences between the routes.
6230a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt     */
624d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti    public CompareResult<RouteInfo> compareAllRoutes(LinkProperties target) {
6250a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        /*
6260a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * Duplicate the RouteInfos into removed, we will be removing
6271994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti         * routes which are common between mRoutes and target
6280a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * leaving the routes that are different. And route address which
6290a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         * are in target but not in mRoutes are placed in added.
6300a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt         */
6310a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        CompareResult<RouteInfo> result = new CompareResult<RouteInfo>();
6320a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
633419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        result.removed = getAllRoutes();
6340a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        result.added.clear();
6350a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        if (target != null) {
636419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            for (RouteInfo r : target.getAllRoutes()) {
6370a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                if (! result.removed.remove(r)) {
6380a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                    result.added.add(r);
6390a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt                }
6400a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt            }
6410a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        }
6420a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        return result;
6430a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    }
6440a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
645992f25257938ecc0378514f21c6e6e6375272976Paul Jensen    /**
646992f25257938ecc0378514f21c6e6e6375272976Paul Jensen     * Compares all interface names in this LinkProperties with another
647992f25257938ecc0378514f21c6e6e6375272976Paul Jensen     * LinkProperties, examining both the the base link and all stacked links.
648992f25257938ecc0378514f21c6e6e6375272976Paul Jensen     *
649992f25257938ecc0378514f21c6e6e6375272976Paul Jensen     * @param target a LinkProperties with the new list of interface names
650992f25257938ecc0378514f21c6e6e6375272976Paul Jensen     * @return the differences between the interface names.
651992f25257938ecc0378514f21c6e6e6375272976Paul Jensen     * @hide
652992f25257938ecc0378514f21c6e6e6375272976Paul Jensen     */
653992f25257938ecc0378514f21c6e6e6375272976Paul Jensen    public CompareResult<String> compareAllInterfaceNames(LinkProperties target) {
654992f25257938ecc0378514f21c6e6e6375272976Paul Jensen        /*
655992f25257938ecc0378514f21c6e6e6375272976Paul Jensen         * Duplicate the interface names into removed, we will be removing
656992f25257938ecc0378514f21c6e6e6375272976Paul Jensen         * interface names which are common between this and target
657992f25257938ecc0378514f21c6e6e6375272976Paul Jensen         * leaving the interface names that are different. And interface names which
658992f25257938ecc0378514f21c6e6e6375272976Paul Jensen         * are in target but not in this are placed in added.
659992f25257938ecc0378514f21c6e6e6375272976Paul Jensen         */
660992f25257938ecc0378514f21c6e6e6375272976Paul Jensen        CompareResult<String> result = new CompareResult<String>();
661992f25257938ecc0378514f21c6e6e6375272976Paul Jensen
662992f25257938ecc0378514f21c6e6e6375272976Paul Jensen        result.removed = getAllInterfaceNames();
663992f25257938ecc0378514f21c6e6e6375272976Paul Jensen        result.added.clear();
664992f25257938ecc0378514f21c6e6e6375272976Paul Jensen        if (target != null) {
665992f25257938ecc0378514f21c6e6e6375272976Paul Jensen            for (String r : target.getAllInterfaceNames()) {
666992f25257938ecc0378514f21c6e6e6375272976Paul Jensen                if (! result.removed.remove(r)) {
667992f25257938ecc0378514f21c6e6e6375272976Paul Jensen                    result.added.add(r);
668992f25257938ecc0378514f21c6e6e6375272976Paul Jensen                }
669992f25257938ecc0378514f21c6e6e6375272976Paul Jensen            }
670992f25257938ecc0378514f21c6e6e6375272976Paul Jensen        }
671992f25257938ecc0378514f21c6e6e6375272976Paul Jensen        return result;
672992f25257938ecc0378514f21c6e6e6375272976Paul Jensen    }
673992f25257938ecc0378514f21c6e6e6375272976Paul Jensen
6740a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
6754e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    @Override
6764e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    /**
6774e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * generate hashcode based on significant fields
6784e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * Equal objects must produce the same hash code, while unequal objects
6794e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     * may have the same hash codes.
6804e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang     */
6814e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    public int hashCode() {
6824e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
6834e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang                + mLinkAddresses.size() * 31
6844e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang                + mDnses.size() * 37
6858058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt                + ((null == mDomains) ? 0 : mDomains.hashCode())
686aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                + mRoutes.size() * 41
687419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode())
6889d9b74a900696191048aa97cc3c854072640428bsy.yun                + mStackedLinks.hashCode() * 47)
6899d9b74a900696191048aa97cc3c854072640428bsy.yun                + mMtu * 51;
6904e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
6914e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
69247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    /**
69347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     * Implement the Parcelable interface.
69447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     */
69537e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public void writeToParcel(Parcel dest, int flags) {
69647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        dest.writeString(getInterfaceName());
697ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        dest.writeInt(mLinkAddresses.size());
698ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff        for(LinkAddress linkAddress : mLinkAddresses) {
699ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff            dest.writeParcelable(linkAddress, flags);
70047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        }
701ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff
70247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        dest.writeInt(mDnses.size());
70347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        for(InetAddress d : mDnses) {
70447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            dest.writeByteArray(d.getAddress());
70547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        }
7068058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt        dest.writeString(mDomains);
7079d9b74a900696191048aa97cc3c854072640428bsy.yun        dest.writeInt(mMtu);
708aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        dest.writeInt(mRoutes.size());
709aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        for(RouteInfo route : mRoutes) {
710aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeParcelable(route, flags);
71147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        }
712992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt
71347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        if (mHttpProxy != null) {
71447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            dest.writeByte((byte)1);
71547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            dest.writeParcelable(mHttpProxy, flags);
71647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        } else {
71747f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            dest.writeByte((byte)0);
71847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        }
719419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        ArrayList<LinkProperties> stackedLinks = new ArrayList(mStackedLinks.values());
720419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        dest.writeList(stackedLinks);
72147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    }
72247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
72347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt    /**
72447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     * Implement the Parcelable interface.
72547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt     */
72637e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt    public static final Creator<LinkProperties> CREATOR =
72737e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt        new Creator<LinkProperties>() {
72837e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt            public LinkProperties createFromParcel(Parcel in) {
72937e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt                LinkProperties netProp = new LinkProperties();
7304717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt
73147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                String iface = in.readString();
73247f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                if (iface != null) {
7334717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt                    netProp.setInterfaceName(iface);
73447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
73547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                int addressCount = in.readInt();
73647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                for (int i=0; i<addressCount; i++) {
737ed5d7d17c9e9837ce7a6a10698cce9f6e4101acdIrfan Sheriff                    netProp.addLinkAddress((LinkAddress)in.readParcelable(null));
73847f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
73947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                addressCount = in.readInt();
74047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                for (int i=0; i<addressCount; i++) {
74147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                    try {
7421cf56ab9c68334d9124c52bcede06aaa0b17c730Irfan Sheriff                        netProp.addDns(InetAddress.getByAddress(in.createByteArray()));
74347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                    } catch (UnknownHostException e) { }
74447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
7458058f621891b41c6864b6004c1c47647436a0ac1Robert Greenwalt                netProp.setDomains(in.readString());
7469d9b74a900696191048aa97cc3c854072640428bsy.yun                netProp.setMtu(in.readInt());
747992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt                addressCount = in.readInt();
748992564e481af13cbcb058ee801f9254a520c54a1Robert Greenwalt                for (int i=0; i<addressCount; i++) {
749aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                    netProp.addRoute((RouteInfo)in.readParcelable(null));
75047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
75147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                if (in.readByte() == 1) {
752207900c23b26d0df9ab28c709db4a1007d7d7904Jason Monk                    netProp.setHttpProxy((ProxyInfo)in.readParcelable(null));
75347f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                }
754419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                ArrayList<LinkProperties> stackedLinks = new ArrayList<LinkProperties>();
755419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                in.readList(stackedLinks, LinkProperties.class.getClassLoader());
756419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                for (LinkProperties stackedLink: stackedLinks) {
757419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                    netProp.addStackedLink(stackedLink);
758419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti                }
75947f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt                return netProp;
76047f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            }
76147f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt
76237e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt            public LinkProperties[] newArray(int size) {
76337e65ebb7eb932e1a144b1cab262e11ca5fd109bRobert Greenwalt                return new LinkProperties[size];
76447f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt            }
76547f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt        };
76647f69fe2999e46004f2f2463b70d38de9ff7079aRobert Greenwalt}
767