1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net;
18
19import android.os.Parcelable;
20import android.os.Parcel;
21import android.text.TextUtils;
22import android.util.Log;
23
24import java.net.InetAddress;
25import java.net.UnknownHostException;
26import java.util.ArrayList;
27import java.util.Collection;
28import java.util.Iterator;
29
30/**
31 * A simple object for retrieving the results of a DHCP request.
32 * Optimized (attempted) for that jni interface
33 * TODO - remove when DhcpInfo is deprecated.  Move the remaining api to LinkProperties.
34 * @hide
35 */
36public class DhcpResults implements Parcelable {
37    private static final String TAG = "DhcpResults";
38
39    public final LinkProperties linkProperties;
40
41    public InetAddress serverAddress;
42
43    /**
44     * Vendor specific information (from RFC 2132).
45     */
46    public String vendorInfo;
47
48    public int leaseDuration;
49
50    public DhcpResults() {
51        linkProperties = new LinkProperties();
52    }
53
54    /** copy constructor */
55    public DhcpResults(DhcpResults source) {
56        if (source != null) {
57            linkProperties = new LinkProperties(source.linkProperties);
58            serverAddress = source.serverAddress;
59            leaseDuration = source.leaseDuration;
60            vendorInfo = source.vendorInfo;
61        } else {
62            linkProperties = new LinkProperties();
63        }
64    }
65
66    public DhcpResults(LinkProperties lp) {
67        linkProperties = new LinkProperties(lp);
68    }
69
70    /**
71     * Updates the DHCP fields that need to be retained from
72     * original DHCP request if the current renewal shows them
73     * being empty.
74     */
75    public void updateFromDhcpRequest(DhcpResults orig) {
76        if (orig == null || orig.linkProperties == null) return;
77        if (linkProperties.getRoutes().size() == 0) {
78            for (RouteInfo r : orig.linkProperties.getRoutes()) linkProperties.addRoute(r);
79        }
80        if (linkProperties.getDnses().size() == 0) {
81            for (InetAddress d : orig.linkProperties.getDnses()) linkProperties.addDns(d);
82        }
83    }
84
85    /**
86     * Test if this DHCP lease includes vendor hint that network link is
87     * metered, and sensitive to heavy data transfers.
88     */
89    public boolean hasMeteredHint() {
90        if (vendorInfo != null) {
91            return vendorInfo.contains("ANDROID_METERED");
92        } else {
93            return false;
94        }
95    }
96
97    public void clear() {
98        linkProperties.clear();
99        serverAddress = null;
100        vendorInfo = null;
101        leaseDuration = 0;
102    }
103
104    @Override
105    public String toString() {
106        StringBuffer str = new StringBuffer(linkProperties.toString());
107
108        str.append(" DHCP server ").append(serverAddress);
109        str.append(" Vendor info ").append(vendorInfo);
110        str.append(" lease ").append(leaseDuration).append(" seconds");
111
112        return str.toString();
113    }
114
115    @Override
116    public boolean equals(Object obj) {
117        if (this == obj) return true;
118
119        if (!(obj instanceof DhcpResults)) return false;
120
121        DhcpResults target = (DhcpResults)obj;
122
123        if (linkProperties == null) {
124            if (target.linkProperties != null) return false;
125        } else if (!linkProperties.equals(target.linkProperties)) return false;
126        if (serverAddress == null) {
127            if (target.serverAddress != null) return false;
128        } else if (!serverAddress.equals(target.serverAddress)) return false;
129        if (vendorInfo == null) {
130            if (target.vendorInfo != null) return false;
131        } else if (!vendorInfo.equals(target.vendorInfo)) return false;
132        if (leaseDuration != target.leaseDuration) return false;
133
134        return true;
135    }
136
137    /** Implement the Parcelable interface */
138    public int describeContents() {
139        return 0;
140    }
141
142    /** Implement the Parcelable interface */
143    public void writeToParcel(Parcel dest, int flags) {
144        linkProperties.writeToParcel(dest, flags);
145
146        dest.writeInt(leaseDuration);
147
148        if (serverAddress != null) {
149            dest.writeByte((byte)1);
150            dest.writeByteArray(serverAddress.getAddress());
151        } else {
152            dest.writeByte((byte)0);
153        }
154
155        dest.writeString(vendorInfo);
156    }
157
158    /** Implement the Parcelable interface */
159    public static final Creator<DhcpResults> CREATOR =
160        new Creator<DhcpResults>() {
161            public DhcpResults createFromParcel(Parcel in) {
162                DhcpResults prop = new DhcpResults((LinkProperties)in.readParcelable(null));
163
164                prop.leaseDuration = in.readInt();
165
166                if (in.readByte() == 1) {
167                    try {
168                        prop.serverAddress = InetAddress.getByAddress(in.createByteArray());
169                    } catch (UnknownHostException e) {}
170                }
171
172                prop.vendorInfo = in.readString();
173
174                return prop;
175            }
176
177            public DhcpResults[] newArray(int size) {
178                return new DhcpResults[size];
179            }
180        };
181
182    // Utils for jni population - false on success
183    public void setInterfaceName(String interfaceName) {
184        linkProperties.setInterfaceName(interfaceName);
185    }
186
187    public boolean addLinkAddress(String addrString, int prefixLength) {
188        InetAddress addr;
189        try {
190            addr = NetworkUtils.numericToInetAddress(addrString);
191        } catch (IllegalArgumentException e) {
192            Log.e(TAG, "addLinkAddress failed with addrString " + addrString);
193            return true;
194        }
195
196        LinkAddress linkAddress = new LinkAddress(addr, prefixLength);
197        linkProperties.addLinkAddress(linkAddress);
198
199        RouteInfo routeInfo = new RouteInfo(linkAddress);
200        linkProperties.addRoute(routeInfo);
201        return false;
202    }
203
204    public boolean addGateway(String addrString) {
205        try {
206            linkProperties.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(addrString)));
207        } catch (IllegalArgumentException e) {
208            Log.e(TAG, "addGateway failed with addrString " + addrString);
209            return true;
210        }
211        return false;
212    }
213
214    public boolean addDns(String addrString) {
215        if (TextUtils.isEmpty(addrString) == false) {
216            try {
217                linkProperties.addDns(NetworkUtils.numericToInetAddress(addrString));
218            } catch (IllegalArgumentException e) {
219                Log.e(TAG, "addDns failed with addrString " + addrString);
220                return true;
221            }
222        }
223        return false;
224    }
225
226    public boolean setServerAddress(String addrString) {
227        try {
228            serverAddress = NetworkUtils.numericToInetAddress(addrString);
229        } catch (IllegalArgumentException e) {
230            Log.e(TAG, "setServerAddress failed with addrString " + addrString);
231            return true;
232        }
233        return false;
234    }
235
236    public void setLeaseDuration(int duration) {
237        leaseDuration = duration;
238    }
239
240    public void setVendorInfo(String info) {
241        vendorInfo = info;
242    }
243
244    public void setDomains(String domains) {
245        linkProperties.setDomains(domains);
246    }
247}
248