2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 import android.net.NetworkUtils;
20 import android.os.Parcelable;
21 import android.os.Parcel;
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;
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}.
40 public class Network implements Parcelable {
45 public final int netId;
47 private NetworkBoundSocketFactory mNetworkBoundSocketFactory = null;
52 public Network(int netId) {
59 public Network(Network that) {
60 this.netId = that.netId;
64 * Operates the same as {@code InetAddress.getAllByName} except that host
65 * resolution is done on this network.
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.
71 public InetAddress[] getAllByName(String host) throws UnknownHostException {
72 return InetAddress.getAllByNameOnNet(host, netId);
76 * Operates the same as {@code InetAddress.getByName} except that host
77 * resolution is done on this network.
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.
85 public InetAddress getByName(String host) throws UnknownHostException {
86 return InetAddress.getByNameOnNet(host, netId);
90 * A {@code SocketFactory} that produces {@code Socket}'s bound to this network.
92 private class NetworkBoundSocketFactory extends SocketFactory {
93 private final int mNetId;
95 public NetworkBoundSocketFactory(int netId) {
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++) {
106 socket.connect(new InetSocketAddress(hostAddresses[i], port));
108 } catch (IOException e) {
111 // Try last address. Do throw exceptions.
112 socket.connect(new InetSocketAddress(hostAddresses[hostAddresses.length - 1], port));
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);
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));
133 public Socket createSocket(InetAddress host, int port) throws IOException {
134 Socket socket = createSocket();
135 socket.connect(new InetSocketAddress(host, port));
140 public Socket createSocket(String host, int port) throws IOException {
141 Socket socket = createSocket();
142 connectToHost(socket, host, port);
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.");
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.
165 * @return a {@link SocketFactory} which produces {@link Socket} instances bound to this
168 public SocketFactory getSocketFactory() {
169 if (mNetworkBoundSocketFactory == null) {
170 mNetworkBoundSocketFactory = new NetworkBoundSocketFactory(netId);
172 return mNetworkBoundSocketFactory;
175 // implement the Parcelable interface
176 public int describeContents() {
179 public void writeToParcel(Parcel dest, int flags) {
180 dest.writeInt(netId);
183 public static final Creator<Network> CREATOR =
184 new Creator<Network>() {
185 public Network createFromParcel(Parcel in) {
186 int netId = in.readInt();
188 return new Network(netId);
191 public Network[] newArray(int size) {
192 return new Network[size];
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;
204 public int hashCode() {
209 public String toString() {
210 return Integer.toString(netId);