OSDN Git Service

am 296459ff: am f4989910: am d32dd294: am b86675f1: am f2c5a9ee: (-s ours) am b9efa1e...
[android-x86/frameworks-base.git] / core / java / android / net / Network.java
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package android.net;
18
19 import android.net.NetworkUtils;
20 import android.os.Parcelable;
21 import android.os.Parcel;
22
23 import java.io.IOException;
24 import java.net.InetAddress;
25 import java.net.InetSocketAddress;
26 import java.net.Socket;
27 import java.net.SocketException;
28 import java.net.UnknownHostException;
29 import javax.net.SocketFactory;
30
31 /**
32  * Identifies a {@code Network}.  This is supplied to applications via
33  * {@link ConnectivityManager.NetworkCallback} in response to the active
34  * {@link ConnectivityManager#requestNetwork} or passive
35  * {@link ConnectivityManager#registerNetworkCallback} calls.
36  * It is used to direct traffic to the given {@code Network}, either on a {@link Socket} basis
37  * through a targeted {@link SocketFactory} or process-wide via
38  * {@link ConnectivityManager#setProcessDefaultNetwork}.
39  */
40 public class Network implements Parcelable {
41
42     /**
43      * @hide
44      */
45     public final int netId;
46
47     private NetworkBoundSocketFactory mNetworkBoundSocketFactory = null;
48
49     /**
50      * @hide
51      */
52     public Network(int netId) {
53         this.netId = netId;
54     }
55
56     /**
57      * @hide
58      */
59     public Network(Network that) {
60         this.netId = that.netId;
61     }
62
63     /**
64      * Operates the same as {@code InetAddress.getAllByName} except that host
65      * resolution is done on this network.
66      *
67      * @param host the hostname or literal IP string to be resolved.
68      * @return the array of addresses associated with the specified host.
69      * @throws UnknownHostException if the address lookup fails.
70      */
71     public InetAddress[] getAllByName(String host) throws UnknownHostException {
72         return InetAddress.getAllByNameOnNet(host, netId);
73     }
74
75     /**
76      * Operates the same as {@code InetAddress.getByName} except that host
77      * resolution is done on this network.
78      *
79      * @param host
80      *            the hostName to be resolved to an address or {@code null}.
81      * @return the {@code InetAddress} instance representing the host.
82      * @throws UnknownHostException
83      *             if the address lookup fails.
84      */
85     public InetAddress getByName(String host) throws UnknownHostException {
86         return InetAddress.getByNameOnNet(host, netId);
87     }
88
89     /**
90      * A {@code SocketFactory} that produces {@code Socket}'s bound to this network.
91      */
92     private class NetworkBoundSocketFactory extends SocketFactory {
93         private final int mNetId;
94
95         public NetworkBoundSocketFactory(int netId) {
96             super();
97             mNetId = netId;
98         }
99
100         private void connectToHost(Socket socket, String host, int port) throws IOException {
101             // Lookup addresses only on this Network.
102             InetAddress[] hostAddresses = getAllByName(host);
103             // Try all but last address ignoring exceptions.
104             for (int i = 0; i < hostAddresses.length - 1; i++) {
105                 try {
106                     socket.connect(new InetSocketAddress(hostAddresses[i], port));
107                     return;
108                 } catch (IOException e) {
109                 }
110             }
111             // Try last address.  Do throw exceptions.
112             socket.connect(new InetSocketAddress(hostAddresses[hostAddresses.length - 1], port));
113         }
114
115         @Override
116         public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
117             Socket socket = createSocket();
118             socket.bind(new InetSocketAddress(localHost, localPort));
119             connectToHost(socket, host, port);
120             return socket;
121         }
122
123         @Override
124         public Socket createSocket(InetAddress address, int port, InetAddress localAddress,
125                 int localPort) throws IOException {
126             Socket socket = createSocket();
127             socket.bind(new InetSocketAddress(localAddress, localPort));
128             socket.connect(new InetSocketAddress(address, port));
129             return socket;
130         }
131
132         @Override
133         public Socket createSocket(InetAddress host, int port) throws IOException {
134             Socket socket = createSocket();
135             socket.connect(new InetSocketAddress(host, port));
136             return socket;
137         }
138
139         @Override
140         public Socket createSocket(String host, int port) throws IOException {
141             Socket socket = createSocket();
142             connectToHost(socket, host, port);
143             return socket;
144         }
145
146         @Override
147         public Socket createSocket() throws IOException {
148             Socket socket = new Socket();
149             // Query a property of the underlying socket to ensure the underlying
150             // socket exists so a file descriptor is available to bind to a network.
151             socket.getReuseAddress();
152             if (!NetworkUtils.bindSocketToNetwork(socket.getFileDescriptor$().getInt$(), mNetId)) {
153                 throw new SocketException("Failed to bind socket to network.");
154             }
155             return socket;
156         }
157     }
158
159     /**
160      * Returns a {@link SocketFactory} bound to this network.  Any {@link Socket} created by
161      * this factory will have its traffic sent over this {@code Network}.  Note that if this
162      * {@code Network} ever disconnects, this factory and any {@link Socket} it produced in the
163      * past or future will cease to work.
164      *
165      * @return a {@link SocketFactory} which produces {@link Socket} instances bound to this
166      *         {@code Network}.
167      */
168     public SocketFactory getSocketFactory() {
169         if (mNetworkBoundSocketFactory == null) {
170             mNetworkBoundSocketFactory = new NetworkBoundSocketFactory(netId);
171         }
172         return mNetworkBoundSocketFactory;
173     }
174
175     // implement the Parcelable interface
176     public int describeContents() {
177         return 0;
178     }
179     public void writeToParcel(Parcel dest, int flags) {
180         dest.writeInt(netId);
181     }
182
183     public static final Creator<Network> CREATOR =
184         new Creator<Network>() {
185             public Network createFromParcel(Parcel in) {
186                 int netId = in.readInt();
187
188                 return new Network(netId);
189             }
190
191             public Network[] newArray(int size) {
192                 return new Network[size];
193             }
194     };
195
196     @Override
197     public boolean equals(Object obj) {
198         if (obj instanceof Network == false) return false;
199         Network other = (Network)obj;
200         return this.netId == other.netId;
201     }
202
203     @Override
204     public int hashCode() {
205         return netId * 11;
206     }
207
208     @Override
209     public String toString() {
210         return Integer.toString(netId);
211     }
212 }