blob: 74b559bcf772376780e8a1452c6b3f57d661f9f7 [file] [log] [blame]
Rahul Ravikumar05336002019-10-14 15:04:32 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation. Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23 * or visit www.oracle.com if you need additional information or have any
24 * questions.
25 */
26package java.net;
27
28import java.io.IOException;
29import java.io.InvalidObjectException;
30import java.io.ObjectInputStream;
31import java.io.ObjectOutputStream;
32import java.io.ObjectStreamException;
33import java.io.ObjectStreamField;
34
35/**
36 *
37 * This class implements an IP Socket Address (IP address + port number)
38 * It can also be a pair (hostname + port number), in which case an attempt
39 * will be made to resolve the hostname. If resolution fails then the address
40 * is said to be <I>unresolved</I> but can still be used on some circumstances
41 * like connecting through a proxy.
42 * <p>
43 * It provides an immutable object used by sockets for binding, connecting, or
44 * as returned values.
45 * <p>
46 * The <i>wildcard</i> is a special local IP address. It usually means "any"
47 * and can only be used for {@code bind} operations.
48 *
49 * @see java.net.Socket
50 * @see java.net.ServerSocket
51 * @since 1.4
52 */
53public class InetSocketAddress
54 extends SocketAddress
55{
56 // Private implementation class pointed to by all public methods.
57 private static class InetSocketAddressHolder {
58 // The hostname of the Socket Address
59 private String hostname;
60 // The IP address of the Socket Address
61 private InetAddress addr;
62 // The port number of the Socket Address
63 private int port;
64
65 private InetSocketAddressHolder(String hostname, InetAddress addr, int port) {
66 this.hostname = hostname;
67 this.addr = addr;
68 this.port = port;
69 }
70
71 private int getPort() {
72 return port;
73 }
74
75 private InetAddress getAddress() {
76 return addr;
77 }
78
79 private String getHostName() {
80 if (hostname != null)
81 return hostname;
82 if (addr != null)
83 return addr.getHostName();
84 return null;
85 }
86
87 private String getHostString() {
88 if (hostname != null)
89 return hostname;
90 if (addr != null) {
91 if (addr.holder().getHostName() != null)
92 return addr.holder().getHostName();
93 else
94 return addr.getHostAddress();
95 }
96 return null;
97 }
98
99 private boolean isUnresolved() {
100 return addr == null;
101 }
102
103 @Override
104 public String toString() {
105 if (isUnresolved()) {
106 return hostname + ":" + port;
107 } else {
108 return addr.toString() + ":" + port;
109 }
110 }
111
112 @Override
113 public final boolean equals(Object obj) {
114 if (obj == null || !(obj instanceof InetSocketAddressHolder))
115 return false;
116 InetSocketAddressHolder that = (InetSocketAddressHolder)obj;
117 boolean sameIP;
118 if (addr != null)
119 sameIP = addr.equals(that.addr);
120 else if (hostname != null)
121 sameIP = (that.addr == null) &&
122 hostname.equalsIgnoreCase(that.hostname);
123 else
124 sameIP = (that.addr == null) && (that.hostname == null);
125 return sameIP && (port == that.port);
126 }
127
128 @Override
129 public final int hashCode() {
130 if (addr != null)
131 return addr.hashCode() + port;
132 if (hostname != null)
133 return hostname.toLowerCase().hashCode() + port;
134 return port;
135 }
136 }
137
138 private final transient InetSocketAddressHolder holder;
139
140 private static final long serialVersionUID = 5076001401234631237L;
141
142 private static int checkPort(int port) {
143 if (port < 0 || port > 0xFFFF)
144 throw new IllegalArgumentException("port out of range:" + port);
145 return port;
146 }
147
148 private static String checkHost(String hostname) {
149 if (hostname == null)
150 throw new IllegalArgumentException("hostname can't be null");
151 return hostname;
152 }
153
154 // BEGIN Android-added: InetSocketAddress() ctor used by IoBridge.
155 /**
156 * @hide internal use only
157 */
158 public InetSocketAddress() {
159 // These will be filled in the native implementation of recvfrom.
160 holder = new InetSocketAddressHolder(null, null, 0);
161 }
162 // END Android-added: InetSocketAddress() ctor used by IoBridge.
163
164 /**
165 * Creates a socket address where the IP address is the wildcard address
166 * and the port number a specified value.
167 * <p>
168 * A valid port value is between 0 and 65535.
169 * A port number of {@code zero} will let the system pick up an
170 * ephemeral port in a {@code bind} operation.
171 * <p>
172 * @param port The port number
173 * @throws IllegalArgumentException if the port parameter is outside the specified
174 * range of valid port values.
175 */
176 public InetSocketAddress(int port) {
177 // Android-changed: Defaults to IPv6.
178 // this(InetAddress.anyLocalAddress(), port);
179 this((InetAddress)null, port);
180 }
181
182 /**
183 *
184 * Creates a socket address from an IP address and a port number.
185 * <p>
186 * A valid port value is between 0 and 65535.
187 * A port number of {@code zero} will let the system pick up an
188 * ephemeral port in a {@code bind} operation.
189 * <P>
190 * A {@code null} address will assign the <i>wildcard</i> address.
191 * <p>
192 * @param addr The IP address
193 * @param port The port number
194 * @throws IllegalArgumentException if the port parameter is outside the specified
195 * range of valid port values.
196 */
197 public InetSocketAddress(InetAddress addr, int port) {
198 holder = new InetSocketAddressHolder(
199 null,
200 // Android-changed: Defaults to IPv6 if addr is null.
201 // addr == null ? InetAddress.anyLocalAddress() : addr,
202 addr == null ? Inet6Address.ANY : addr,
203 checkPort(port));
204 }
205
206 /**
207 *
208 * Creates a socket address from a hostname and a port number.
209 * <p>
210 * An attempt will be made to resolve the hostname into an InetAddress.
211 * If that attempt fails, the address will be flagged as <I>unresolved</I>.
212 * <p>
213 * If there is a security manager, its {@code checkConnect} method
214 * is called with the host name as its argument to check the permission
215 * to resolve it. This could result in a SecurityException.
216 * <P>
217 * A valid port value is between 0 and 65535.
218 * A port number of {@code zero} will let the system pick up an
219 * ephemeral port in a {@code bind} operation.
220 * <P>
221 * @param hostname the Host name
222 * @param port The port number
223 * @throws IllegalArgumentException if the port parameter is outside the range
224 * of valid port values, or if the hostname parameter is <TT>null</TT>.
225 * @throws SecurityException if a security manager is present and
226 * permission to resolve the host name is
227 * denied.
228 * @see #isUnresolved()
229 */
230 public InetSocketAddress(String hostname, int port) {
231 checkHost(hostname);
232 InetAddress addr = null;
233 String host = null;
234 try {
235 addr = InetAddress.getByName(hostname);
236 } catch(UnknownHostException e) {
237 host = hostname;
238 }
239 holder = new InetSocketAddressHolder(host, addr, checkPort(port));
240 }
241
242 // private constructor for creating unresolved instances
243 private InetSocketAddress(int port, String hostname) {
244 holder = new InetSocketAddressHolder(hostname, null, port);
245 }
246
247 /**
248 *
249 * Creates an unresolved socket address from a hostname and a port number.
250 * <p>
251 * No attempt will be made to resolve the hostname into an InetAddress.
252 * The address will be flagged as <I>unresolved</I>.
253 * <p>
254 * A valid port value is between 0 and 65535.
255 * A port number of {@code zero} will let the system pick up an
256 * ephemeral port in a {@code bind} operation.
257 * <P>
258 * @param host the Host name
259 * @param port The port number
260 * @throws IllegalArgumentException if the port parameter is outside
261 * the range of valid port values, or if the hostname
262 * parameter is <TT>null</TT>.
263 * @see #isUnresolved()
264 * @return a {@code InetSocketAddress} representing the unresolved
265 * socket address
266 * @since 1.5
267 */
268 public static InetSocketAddress createUnresolved(String host, int port) {
269 return new InetSocketAddress(checkPort(port), checkHost(host));
270 }
271
272 /**
273 * @serialField hostname String
274 * @serialField addr InetAddress
275 * @serialField port int
276 */
277 private static final ObjectStreamField[] serialPersistentFields = {
278 new ObjectStreamField("hostname", String.class),
279 new ObjectStreamField("addr", InetAddress.class),
280 new ObjectStreamField("port", int.class)};
281
282 private void writeObject(ObjectOutputStream out)
283 throws IOException
284 {
285 // Don't call defaultWriteObject()
286 ObjectOutputStream.PutField pfields = out.putFields();
287 pfields.put("hostname", holder.hostname);
288 pfields.put("addr", holder.addr);
289 pfields.put("port", holder.port);
290 out.writeFields();
291 }
292
293 private void readObject(ObjectInputStream in)
294 throws IOException, ClassNotFoundException
295 {
296 // Don't call defaultReadObject()
297 ObjectInputStream.GetField oisFields = in.readFields();
298 final String oisHostname = (String)oisFields.get("hostname", null);
299 final InetAddress oisAddr = (InetAddress)oisFields.get("addr", null);
300 final int oisPort = oisFields.get("port", -1);
301
302 // Check that our invariants are satisfied
303 checkPort(oisPort);
304 if (oisHostname == null && oisAddr == null)
305 throw new InvalidObjectException("hostname and addr " +
306 "can't both be null");
307
308 InetSocketAddressHolder h = new InetSocketAddressHolder(oisHostname,
309 oisAddr,
310 oisPort);
311 UNSAFE.putObject(this, FIELDS_OFFSET, h);
312 }
313
314 private void readObjectNoData()
315 throws ObjectStreamException
316 {
317 throw new InvalidObjectException("Stream data required");
318 }
319
320 private static final long FIELDS_OFFSET;
321 private static final sun.misc.Unsafe UNSAFE;
322 static {
323 try {
324 sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
325 FIELDS_OFFSET = unsafe.objectFieldOffset(
326 InetSocketAddress.class.getDeclaredField("holder"));
327 UNSAFE = unsafe;
328 } catch (ReflectiveOperationException e) {
329 throw new Error(e);
330 }
331 }
332
333 /**
334 * Gets the port number.
335 *
336 * @return the port number.
337 */
338 public final int getPort() {
339 return holder.getPort();
340 }
341
342 /**
343 *
344 * Gets the {@code InetAddress}.
345 *
346 * @return the InetAdress or {@code null} if it is unresolved.
347 */
348 public final InetAddress getAddress() {
349 return holder.getAddress();
350 }
351
352 /**
353 * Gets the {@code hostname}.
354 * Note: This method may trigger a name service reverse lookup if the
355 * address was created with a literal IP address.
356 *
357 * @return the hostname part of the address.
358 */
359 public final String getHostName() {
360 return holder.getHostName();
361 }
362
363 /**
364 * Returns the hostname, or the String form of the address if it
365 * doesn't have a hostname (it was created using a literal).
366 * This has the benefit of <b>not</b> attempting a reverse lookup.
367 *
368 * @return the hostname, or String representation of the address.
369 * @since 1.7
370 */
371 public final String getHostString() {
372 return holder.getHostString();
373 }
374
375 /**
376 * Checks whether the address has been resolved or not.
377 *
378 * @return {@code true} if the hostname couldn't be resolved into
379 * an {@code InetAddress}.
380 */
381 public final boolean isUnresolved() {
382 return holder.isUnresolved();
383 }
384
385 /**
386 * Constructs a string representation of this InetSocketAddress.
387 * This String is constructed by calling toString() on the InetAddress
388 * and concatenating the port number (with a colon). If the address
389 * is unresolved then the part before the colon will only contain the hostname.
390 *
391 * @return a string representation of this object.
392 */
393 @Override
394 public String toString() {
395 return holder.toString();
396 }
397
398 /**
399 * Compares this object against the specified object.
400 * The result is {@code true} if and only if the argument is
401 * not {@code null} and it represents the same address as
402 * this object.
403 * <p>
404 * Two instances of {@code InetSocketAddress} represent the same
405 * address if both the InetAddresses (or hostnames if it is unresolved) and port
406 * numbers are equal.
407 * If both addresses are unresolved, then the hostname and the port number
408 * are compared.
409 *
410 * Note: Hostnames are case insensitive. e.g. "FooBar" and "foobar" are
411 * considered equal.
412 *
413 * @param obj the object to compare against.
414 * @return {@code true} if the objects are the same;
415 * {@code false} otherwise.
416 * @see java.net.InetAddress#equals(java.lang.Object)
417 */
418 @Override
419 public final boolean equals(Object obj) {
420 if (obj == null || !(obj instanceof InetSocketAddress))
421 return false;
422 return holder.equals(((InetSocketAddress) obj).holder);
423 }
424
425 /**
426 * Returns a hashcode for this socket address.
427 *
428 * @return a hash code value for this socket address.
429 */
430 @Override
431 public final int hashCode() {
432 return holder.hashCode();
433 }
434}