• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17 
18 package java.net;
19 
20 import java.io.Closeable;
21 import java.io.FileDescriptor;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.nio.channels.SocketChannel;
26 import libcore.io.IoBridge;
27 
28 /**
29  * Provides a client-side TCP socket.
30  */
31 public class Socket implements Closeable {
32     private static SocketImplFactory factory;
33 
34     final SocketImpl impl;
35     private final Proxy proxy;
36 
37     volatile boolean isCreated = false;
38     private boolean isBound = false;
39     private boolean isConnected = false;
40     private boolean isClosed = false;
41     private boolean isInputShutdown = false;
42     private boolean isOutputShutdown = false;
43 
44     private InetAddress localAddress = Inet6Address.ANY;
45 
46     private final Object connectLock = new Object();
47 
48     /**
49      * Creates a new unconnected socket. When a SocketImplFactory is defined it
50      * creates the internal socket implementation, otherwise the default socket
51      * implementation will be used for this socket.
52      *
53      * @see SocketImplFactory
54      * @see SocketImpl
55      */
Socket()56     public Socket() {
57         this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl();
58         this.proxy = null;
59     }
60 
61     /**
62      * Creates a new unconnected socket using the given proxy type. When a
63      * {@code SocketImplFactory} is defined it creates the internal socket
64      * implementation, otherwise the default socket implementation will be used
65      * for this socket.
66      * <p>
67      * Example that will create a socket connection through a {@code SOCKS}
68      * proxy server: <br>
69      * {@code Socket sock = new Socket(new Proxy(Proxy.Type.SOCKS, new
70      * InetSocketAddress("test.domain.org", 2130)));}
71      *
72      * @param proxy
73      *            the specified proxy for this socket.
74      * @throws IllegalArgumentException
75      *             if the argument {@code proxy} is {@code null} or of an
76      *             invalid type.
77      * @see SocketImplFactory
78      * @see SocketImpl
79      */
Socket(Proxy proxy)80     public Socket(Proxy proxy) {
81         if (proxy == null || proxy.type() == Proxy.Type.HTTP) {
82             throw new IllegalArgumentException("Invalid proxy: " + proxy);
83         }
84         this.proxy = proxy;
85         this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl(proxy);
86     }
87 
88     /**
89      * Tries to connect a socket to all IP addresses of the given hostname.
90      *
91      * @param dstName
92      *            the target host name or IP address to connect to.
93      * @param dstPort
94      *            the port on the target host to connect to.
95      * @param localAddress
96      *            the address on the local host to bind to.
97      * @param localPort
98      *            the port on the local host to bind to.
99      * @param streaming
100      *            if {@code true} a streaming socket is returned, a datagram
101      *            socket otherwise.
102      * @throws UnknownHostException
103      *             if the host name could not be resolved into an IP address.
104      * @throws IOException
105      *             if an error occurs while creating the socket.
106      */
tryAllAddresses(String dstName, int dstPort, InetAddress localAddress, int localPort, boolean streaming)107     private void tryAllAddresses(String dstName, int dstPort, InetAddress
108             localAddress, int localPort, boolean streaming) throws IOException {
109         InetAddress[] dstAddresses = InetAddress.getAllByName(dstName);
110         // Loop through all the destination addresses except the last, trying to
111         // connect to each one and ignoring errors. There must be at least one
112         // address, or getAllByName would have thrown UnknownHostException.
113         InetAddress dstAddress;
114         for (int i = 0; i < dstAddresses.length - 1; i++) {
115             dstAddress = dstAddresses[i];
116             try {
117                 checkDestination(dstAddress, dstPort);
118                 startupSocket(dstAddress, dstPort, localAddress, localPort, streaming);
119                 return;
120             } catch (IOException ex) {
121             }
122         }
123 
124         // Now try to connect to the last address in the array, handing back to
125         // the caller any exceptions that are thrown.
126         dstAddress = dstAddresses[dstAddresses.length - 1];
127         checkDestination(dstAddress, dstPort);
128         startupSocket(dstAddress, dstPort, localAddress, localPort, streaming);
129     }
130 
131     /**
132      * Creates a new streaming socket connected to the target host specified by
133      * the parameters {@code dstName} and {@code dstPort}. The socket is bound
134      * to any available port on the local host.
135      *
136      * <p>This implementation tries each IP address for the given hostname (in
137      * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order)
138      * until it either connects successfully or it exhausts the set.
139      *
140      * @param dstName
141      *            the target host name or IP address to connect to.
142      * @param dstPort
143      *            the port on the target host to connect to.
144      * @throws UnknownHostException
145      *             if the host name could not be resolved into an IP address.
146      * @throws IOException
147      *             if an error occurs while creating the socket.
148      */
Socket(String dstName, int dstPort)149     public Socket(String dstName, int dstPort) throws UnknownHostException, IOException {
150         this(dstName, dstPort, null, 0);
151     }
152 
153     /**
154      * Creates a new streaming socket connected to the target host specified by
155      * the parameters {@code dstName} and {@code dstPort}. On the local endpoint
156      * the socket is bound to the given address {@code localAddress} on port
157      * {@code localPort}. If {@code host} is {@code null} a loopback address is used to connect to.
158      *
159      * <p>This implementation tries each IP address for the given hostname (in
160      * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order)
161      * until it either connects successfully or it exhausts the set.
162      *
163      * @param dstName
164      *            the target host name or IP address to connect to.
165      * @param dstPort
166      *            the port on the target host to connect to.
167      * @param localAddress
168      *            the address on the local host to bind to.
169      * @param localPort
170      *            the port on the local host to bind to.
171      * @throws UnknownHostException
172      *             if the host name could not be resolved into an IP address.
173      * @throws IOException
174      *             if an error occurs while creating the socket.
175      */
Socket(String dstName, int dstPort, InetAddress localAddress, int localPort)176     public Socket(String dstName, int dstPort, InetAddress localAddress, int localPort) throws IOException {
177         this();
178         tryAllAddresses(dstName, dstPort, localAddress, localPort, true);
179     }
180 
181     /**
182      * Creates a new streaming or datagram socket connected to the target host
183      * specified by the parameters {@code hostName} and {@code port}. The socket
184      * is bound to any available port on the local host.
185      *
186      * <p>This implementation tries each IP address for the given hostname (in
187      * <a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a> order)
188      * until it either connects successfully or it exhausts the set.
189      *
190      * @param hostName
191      *            the target host name or IP address to connect to.
192      * @param port
193      *            the port on the target host to connect to.
194      * @param streaming
195      *            if {@code true} a streaming socket is returned, a datagram
196      *            socket otherwise.
197      * @throws UnknownHostException
198      *             if the host name could not be resolved into an IP address.
199      * @throws IOException
200      *             if an error occurs while creating the socket.
201      * @deprecated Use {@code Socket(String, int)} instead of this for streaming
202      *             sockets or an appropriate constructor of {@code
203      *             DatagramSocket} for UDP transport.
204      */
205     @Deprecated
Socket(String hostName, int port, boolean streaming)206     public Socket(String hostName, int port, boolean streaming) throws IOException {
207         this();
208         tryAllAddresses(hostName, port, null, 0, streaming);
209     }
210 
211     /**
212      * Creates a new streaming socket connected to the target host specified by
213      * the parameters {@code dstAddress} and {@code dstPort}. The socket is
214      * bound to any available port on the local host using a wildcard address.
215      *
216      * @param dstAddress
217      *            the target host address to connect to.
218      * @param dstPort
219      *            the port on the target host to connect to.
220      * @throws IOException
221      *             if an error occurs while creating the socket.
222      */
Socket(InetAddress dstAddress, int dstPort)223     public Socket(InetAddress dstAddress, int dstPort) throws IOException {
224         this();
225         checkDestination(dstAddress, dstPort);
226         startupSocket(dstAddress, dstPort, null, 0, true);
227     }
228 
229     /**
230      * Creates a new streaming socket connected to the target host specified by
231      * the parameters {@code dstAddress} and {@code dstPort}.
232      *
233      * <p>On the local endpoint the socket is bound to the given address {@code localAddress} on
234      * port {@code localPort}. If {@code localAddress} is {@code null} the socket will be bound to a
235      * wildcard address.
236      *
237      * @param dstAddress
238      *            the target host address to connect to.
239      * @param dstPort
240      *            the port on the target host to connect to.
241      * @param localAddress
242      *            the address on the local host to bind to, or null.
243      * @param localPort
244      *            the port on the local host to bind to.
245      * @throws IOException
246      *             if an error occurs while creating the socket.
247      */
Socket(InetAddress dstAddress, int dstPort, InetAddress localAddress, int localPort)248     public Socket(InetAddress dstAddress, int dstPort,
249             InetAddress localAddress, int localPort) throws IOException {
250         this();
251         checkDestination(dstAddress, dstPort);
252         startupSocket(dstAddress, dstPort, localAddress, localPort, true);
253     }
254 
255     /**
256      * Creates a new streaming or datagram socket connected to the target host
257      * specified by the parameters {@code addr} and {@code port}. The socket is
258      * bound to any available port on the local host using a wildcard address.
259      *
260      * @param addr
261      *            the Internet address to connect to.
262      * @param port
263      *            the port on the target host to connect to.
264      * @param streaming
265      *            if {@code true} a streaming socket is returned, a datagram
266      *            socket otherwise.
267      * @throws IOException
268      *             if an error occurs while creating the socket.
269      * @deprecated Use {@code Socket(InetAddress, int)} instead of this for
270      *             streaming sockets or an appropriate constructor of {@code
271      *             DatagramSocket} for UDP transport.
272      */
273     @Deprecated
Socket(InetAddress addr, int port, boolean streaming)274     public Socket(InetAddress addr, int port, boolean streaming) throws IOException {
275         this();
276         checkDestination(addr, port);
277         startupSocket(addr, port, null, 0, streaming);
278     }
279 
280     /**
281      * Creates an unconnected socket with the given socket implementation.
282      *
283      * @param impl
284      *            the socket implementation to be used.
285      * @throws SocketException
286      *             if an error occurs while creating the socket.
287      */
Socket(SocketImpl impl)288     protected Socket(SocketImpl impl) throws SocketException {
289         this.impl = impl;
290         this.proxy = null;
291     }
292 
293     /**
294      * Checks whether the connection destination satisfies the security policy
295      * and the validity of the port range.
296      *
297      * @param destAddr
298      *            the destination host address.
299      * @param dstPort
300      *            the port on the destination host.
301      */
checkDestination(InetAddress destAddr, int dstPort)302     private void checkDestination(InetAddress destAddr, int dstPort) {
303         if (dstPort < 0 || dstPort > 65535) {
304             throw new IllegalArgumentException("Port out of range: " + dstPort);
305         }
306     }
307 
308     /**
309      * Closes the socket. It is not possible to reconnect or rebind to this
310      * socket thereafter which means a new socket instance has to be created.
311      *
312      * @throws IOException
313      *             if an error occurs while closing the socket.
314      */
close()315     public synchronized void close() throws IOException {
316         isClosed = true;
317         isConnected = false;
318         // RI compatibility: the RI returns the any address (but the original local port) after
319         // close.
320         localAddress = Inet6Address.ANY;
321         impl.close();
322     }
323 
324     /**
325      * Sets the Socket and its related SocketImpl state as if a successful close() took place,
326      * without actually performing an OS close().
327      *
328      * @hide used in java.nio
329      */
onClose()330     public void onClose() {
331         isClosed = true;
332         isConnected = false;
333         // RI compatibility: the RI returns the any address (but the original local port) after
334         // close.
335         localAddress = Inet6Address.ANY;
336         impl.onClose();
337     }
338 
339     /**
340      * Returns the IP address of the target host this socket is connected to, or null if this
341      * socket is not yet connected.
342      */
getInetAddress()343     public InetAddress getInetAddress() {
344         if (!isConnected()) {
345             return null;
346         }
347         return impl.getInetAddress();
348     }
349 
350     /**
351      * Returns an input stream to read data from this socket. If the socket has an associated
352      * {@link SocketChannel} and that channel is in non-blocking mode then reads from the
353      * stream will throw a {@link java.nio.channels.IllegalBlockingModeException}.
354      *
355      * @return the byte-oriented input stream.
356      * @throws IOException
357      *             if an error occurs while creating the input stream or the
358      *             socket is in an invalid state.
359      */
getInputStream()360     public InputStream getInputStream() throws IOException {
361         checkOpenAndCreate(false);
362         if (isInputShutdown()) {
363             throw new SocketException("Socket input is shutdown");
364         }
365         return impl.getInputStream();
366     }
367 
368     /**
369      * Returns this socket's {@link SocketOptions#SO_KEEPALIVE} setting.
370      */
getKeepAlive()371     public boolean getKeepAlive() throws SocketException {
372         checkOpenAndCreate(true);
373         return (Boolean) impl.getOption(SocketOptions.SO_KEEPALIVE);
374     }
375 
376     /**
377      * Returns the local IP address this socket is bound to, or an address for which
378      * {@link InetAddress#isAnyLocalAddress()} returns true if the socket is closed or unbound.
379      */
getLocalAddress()380     public InetAddress getLocalAddress() {
381         return localAddress;
382     }
383 
384     /**
385      * Returns the local port this socket is bound to, or -1 if the socket is unbound. If the socket
386      * has been closed this method will still return the local port the socket was bound to.
387      */
getLocalPort()388     public int getLocalPort() {
389         if (!isBound()) {
390             return -1;
391         }
392         return impl.getLocalPort();
393     }
394 
395     /**
396      * Returns an output stream to write data into this socket. If the socket has an associated
397      * {@link SocketChannel} and that channel is in non-blocking mode then writes to the
398      * stream will throw a {@link java.nio.channels.IllegalBlockingModeException}.
399      *
400      * @return the byte-oriented output stream.
401      * @throws IOException
402      *             if an error occurs while creating the output stream or the
403      *             socket is in an invalid state.
404      */
getOutputStream()405     public OutputStream getOutputStream() throws IOException {
406         checkOpenAndCreate(false);
407         if (isOutputShutdown()) {
408             throw new SocketException("Socket output is shutdown");
409         }
410         return impl.getOutputStream();
411     }
412 
413     /**
414      * Returns the port number of the target host this socket is connected to, or 0 if this socket
415      * is not yet connected.
416      */
getPort()417     public int getPort() {
418         if (!isConnected()) {
419             return 0;
420         }
421         return impl.getPort();
422     }
423 
424     /**
425      * Returns this socket's {@link SocketOptions#SO_LINGER linger} timeout in seconds, or -1
426      * for no linger (i.e. {@code close} will return immediately).
427      */
getSoLinger()428     public int getSoLinger() throws SocketException {
429         checkOpenAndCreate(true);
430         // The RI explicitly guarantees this idiocy in the SocketOptions.setOption documentation.
431         Object value = impl.getOption(SocketOptions.SO_LINGER);
432         if (value instanceof Integer) {
433             return (Integer) value;
434         } else {
435             return -1;
436         }
437     }
438 
439     /**
440      * Returns this socket's {@link SocketOptions#SO_RCVBUF receive buffer size}.
441      */
getReceiveBufferSize()442     public synchronized int getReceiveBufferSize() throws SocketException {
443         checkOpenAndCreate(true);
444         return (Integer) impl.getOption(SocketOptions.SO_RCVBUF);
445     }
446 
447     /**
448      * Returns this socket's {@link SocketOptions#SO_SNDBUF send buffer size}.
449      */
getSendBufferSize()450     public synchronized int getSendBufferSize() throws SocketException {
451         checkOpenAndCreate(true);
452         return (Integer) impl.getOption(SocketOptions.SO_SNDBUF);
453     }
454 
455     /**
456      * Returns this socket's {@link SocketOptions#SO_TIMEOUT receive timeout}.
457      */
getSoTimeout()458     public synchronized int getSoTimeout() throws SocketException {
459         checkOpenAndCreate(true);
460         return (Integer) impl.getOption(SocketOptions.SO_TIMEOUT);
461     }
462 
463     /**
464      * Returns this socket's {@code SocketOptions#TCP_NODELAY} setting.
465      */
getTcpNoDelay()466     public boolean getTcpNoDelay() throws SocketException {
467         checkOpenAndCreate(true);
468         return (Boolean) impl.getOption(SocketOptions.TCP_NODELAY);
469     }
470 
471     /**
472      * Sets this socket's {@link SocketOptions#SO_KEEPALIVE} option.
473      */
setKeepAlive(boolean keepAlive)474     public void setKeepAlive(boolean keepAlive) throws SocketException {
475         if (impl != null) {
476             checkOpenAndCreate(true);
477             impl.setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(keepAlive));
478         }
479     }
480 
481     /**
482      * Sets the internal factory for creating socket implementations. This may
483      * only be executed once during the lifetime of the application.
484      *
485      * @param fac
486      *            the socket implementation factory to be set.
487      * @throws IOException
488      *             if the factory has been already set.
489      */
setSocketImplFactory(SocketImplFactory fac)490     public static synchronized void setSocketImplFactory(SocketImplFactory fac)
491             throws IOException {
492         if (factory != null) {
493             throw new SocketException("Factory already set");
494         }
495         factory = fac;
496     }
497 
498     /**
499      * Sets this socket's {@link SocketOptions#SO_SNDBUF send buffer size}.
500      */
setSendBufferSize(int size)501     public synchronized void setSendBufferSize(int size) throws SocketException {
502         checkOpenAndCreate(true);
503         if (size < 1) {
504             throw new IllegalArgumentException("size < 1");
505         }
506         impl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
507     }
508 
509     /**
510      * Sets this socket's {@link SocketOptions#SO_RCVBUF receive buffer size}.
511      */
setReceiveBufferSize(int size)512     public synchronized void setReceiveBufferSize(int size) throws SocketException {
513         checkOpenAndCreate(true);
514         if (size < 1) {
515             throw new IllegalArgumentException("size < 1");
516         }
517         impl.setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
518     }
519 
520     /**
521      * Sets this socket's {@link SocketOptions#SO_LINGER linger} timeout in seconds.
522      * If {@code on} is false, {@code timeout} is irrelevant.
523      */
setSoLinger(boolean on, int timeout)524     public void setSoLinger(boolean on, int timeout) throws SocketException {
525         checkOpenAndCreate(true);
526         // The RI explicitly guarantees this idiocy in the SocketOptions.setOption documentation.
527         if (on && timeout < 0) {
528             throw new IllegalArgumentException("timeout < 0");
529         }
530         if (on) {
531             impl.setOption(SocketOptions.SO_LINGER, Integer.valueOf(timeout));
532         } else {
533             impl.setOption(SocketOptions.SO_LINGER, Boolean.FALSE);
534         }
535     }
536 
537     /**
538      * Sets this socket's {@link SocketOptions#SO_TIMEOUT read timeout} in milliseconds.
539      * Use 0 for no timeout.
540      * To take effect, this option must be set before the blocking method was called.
541      */
setSoTimeout(int timeout)542     public synchronized void setSoTimeout(int timeout) throws SocketException {
543         checkOpenAndCreate(true);
544         if (timeout < 0) {
545             throw new IllegalArgumentException("timeout < 0");
546         }
547         impl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
548     }
549 
550     /**
551      * Sets this socket's {@link SocketOptions#TCP_NODELAY} option.
552      */
setTcpNoDelay(boolean on)553     public void setTcpNoDelay(boolean on) throws SocketException {
554         checkOpenAndCreate(true);
555         impl.setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
556     }
557 
558     /**
559      * Creates a stream socket, binds it to the nominated local address/port,
560      * then connects it to the nominated destination address/port.
561      *
562      * @param dstAddress
563      *            the destination host address.
564      * @param dstPort
565      *            the port on the destination host.
566      * @param localAddress
567      *            the address on the local machine to bind.
568      * @param localPort
569      *            the port on the local machine to bind.
570      * @throws IOException
571      *             thrown if an error occurs during the bind or connect
572      *             operations.
573      */
startupSocket(InetAddress dstAddress, int dstPort, InetAddress localAddress, int localPort, boolean streaming)574     private void startupSocket(InetAddress dstAddress, int dstPort,
575             InetAddress localAddress, int localPort, boolean streaming)
576             throws IOException {
577 
578         if (localPort < 0 || localPort > 65535) {
579             throw new IllegalArgumentException("Local port out of range: " + localPort);
580         }
581 
582         InetAddress addr = localAddress == null ? Inet6Address.ANY : localAddress;
583         synchronized (this) {
584             impl.create(streaming);
585             isCreated = true;
586             try {
587                 if (!streaming || !usingSocks()) {
588                     impl.bind(addr, localPort);
589                 }
590                 isBound = true;
591                 cacheLocalAddress();
592                 impl.connect(dstAddress, dstPort);
593                 isConnected = true;
594                 cacheLocalAddress();
595             } catch (IOException e) {
596                 impl.close();
597                 throw e;
598             }
599         }
600     }
601 
usingSocks()602     private boolean usingSocks() {
603         return proxy != null && proxy.type() == Proxy.Type.SOCKS;
604     }
605 
606     /**
607      * Returns a {@code String} containing a concise, human-readable description of the
608      * socket.
609      *
610      * @return the textual representation of this socket.
611      */
612     @Override
toString()613     public String toString() {
614         if (!isConnected()) {
615             return "Socket[unconnected]";
616         }
617         return impl.toString();
618     }
619 
620     /**
621      * Closes the input stream of this socket. Any further data sent to this
622      * socket will be discarded. Reading from this socket after this method has
623      * been called will return the value {@code EOF}.
624      *
625      * @throws IOException
626      *             if an error occurs while closing the socket input stream.
627      * @throws SocketException
628      *             if the input stream is already closed.
629      */
shutdownInput()630     public void shutdownInput() throws IOException {
631         if (isInputShutdown()) {
632             throw new SocketException("Socket input is shutdown");
633         }
634         checkOpenAndCreate(false);
635         impl.shutdownInput();
636         isInputShutdown = true;
637     }
638 
639     /**
640      * Closes the output stream of this socket. All buffered data will be sent
641      * followed by the termination sequence. Writing to the closed output stream
642      * will cause an {@code IOException}.
643      *
644      * @throws IOException
645      *             if an error occurs while closing the socket output stream.
646      * @throws SocketException
647      *             if the output stream is already closed.
648      */
shutdownOutput()649     public void shutdownOutput() throws IOException {
650         if (isOutputShutdown()) {
651             throw new SocketException("Socket output is shutdown");
652         }
653         checkOpenAndCreate(false);
654         impl.shutdownOutput();
655         isOutputShutdown = true;
656     }
657 
658     /**
659      * Checks whether the socket is closed, and throws an exception. Otherwise
660      * creates the underlying SocketImpl.
661      *
662      * @throws SocketException
663      *             if the socket is closed.
664      */
checkOpenAndCreate(boolean create)665     private void checkOpenAndCreate(boolean create) throws SocketException {
666         if (isClosed()) {
667             throw new SocketException("Socket is closed");
668         }
669         if (!create) {
670             if (!isConnected()) {
671                 throw new SocketException("Socket is not connected");
672                 // a connected socket must be created
673             }
674 
675             /*
676              * return directly to fix a possible bug, if !create, should return
677              * here
678              */
679             return;
680         }
681         if (isCreated) {
682             return;
683         }
684         synchronized (this) {
685             if (isCreated) {
686                 return;
687             }
688             try {
689                 impl.create(true);
690             } catch (SocketException e) {
691                 throw e;
692             } catch (IOException e) {
693                 throw new SocketException(e.toString());
694             }
695             isCreated = true;
696         }
697     }
698 
699     /**
700      * Returns the local address and port of this socket as a SocketAddress or null if the socket
701      * has never been bound. If the socket is closed but has previously been bound then an address
702      * for which {@link InetAddress#isAnyLocalAddress()} returns true will be returned with the
703      * previously-bound port. This is useful on multihomed hosts.
704      */
getLocalSocketAddress()705     public SocketAddress getLocalSocketAddress() {
706         if (!isBound()) {
707             return null;
708         }
709         return new InetSocketAddress(getLocalAddress(), getLocalPort());
710     }
711 
712     /**
713      * Returns the remote address and port of this socket as a {@code
714      * SocketAddress} or null if the socket is not connected.
715      *
716      * @return the remote socket address and port.
717      */
getRemoteSocketAddress()718     public SocketAddress getRemoteSocketAddress() {
719         if (!isConnected()) {
720             return null;
721         }
722         return new InetSocketAddress(getInetAddress(), getPort());
723     }
724 
725     /**
726      * Returns whether this socket is bound to a local address and port.
727      *
728      * @return {@code true} if the socket is bound to a local address, {@code
729      *         false} otherwise.
730      */
isBound()731     public boolean isBound() {
732         return isBound;
733     }
734 
735     /**
736      * Returns whether this socket is connected to a remote host.
737      *
738      * @return {@code true} if the socket is connected, {@code false} otherwise.
739      */
isConnected()740     public boolean isConnected() {
741         return isConnected;
742     }
743 
744     /**
745      * Returns whether this socket is closed.
746      *
747      * @return {@code true} if the socket is closed, {@code false} otherwise.
748      */
isClosed()749     public boolean isClosed() {
750         return isClosed;
751     }
752 
753     /**
754      * Binds this socket to the given local host address and port specified by
755      * the SocketAddress {@code localAddr}. If {@code localAddr} is set to
756      * {@code null}, this socket will be bound to an available local address on
757      * any free port.
758      *
759      * @param localAddr
760      *            the specific address and port on the local machine to bind to.
761      * @throws IllegalArgumentException
762      *             if the given SocketAddress is invalid or not supported.
763      * @throws IOException
764      *             if the socket is already bound or an error occurs while
765      *             binding.
766      */
bind(SocketAddress localAddr)767     public void bind(SocketAddress localAddr) throws IOException {
768         checkOpenAndCreate(true);
769         if (isBound()) {
770             throw new BindException("Socket is already bound");
771         }
772 
773         int port;
774         InetAddress addr;
775         if (localAddr == null) {
776             port = 0;
777             addr = Inet6Address.ANY;
778         } else {
779             if (!(localAddr instanceof InetSocketAddress)) {
780                 throw new IllegalArgumentException("Local address not an InetSocketAddress: " +
781                         localAddr.getClass());
782             }
783             InetSocketAddress inetAddr = (InetSocketAddress) localAddr;
784             if ((addr = inetAddr.getAddress()) == null) {
785                 throw new UnknownHostException("Host is unresolved: " + inetAddr.getHostName());
786             }
787             port = inetAddr.getPort();
788         }
789 
790         synchronized (this) {
791             try {
792                 impl.bind(addr, port);
793                 isBound = true;
794                 cacheLocalAddress();
795             } catch (IOException e) {
796                 impl.close();
797                 throw e;
798             }
799         }
800     }
801 
802     /**
803      * Sets the Socket and its related SocketImpl state as if a successful bind() took place,
804      * without actually performing an OS bind().
805      *
806      * @hide used in java.nio
807      */
onBind(InetAddress localAddress, int localPort)808     public void onBind(InetAddress localAddress, int localPort) {
809         isBound = true;
810         this.localAddress = localAddress;
811         impl.onBind(localAddress, localPort);
812     }
813 
814     /**
815      * Connects this socket to the given remote host address and port specified
816      * by the SocketAddress {@code remoteAddr}.
817      *
818      * @param remoteAddr
819      *            the address and port of the remote host to connect to.
820      * @throws IllegalArgumentException
821      *             if the given SocketAddress is invalid or not supported.
822      * @throws IOException
823      *             if the socket is already connected or an error occurs while
824      *             connecting.
825      */
connect(SocketAddress remoteAddr)826     public void connect(SocketAddress remoteAddr) throws IOException {
827         connect(remoteAddr, 0);
828     }
829 
830     /**
831      * Connects this socket to the given remote host address and port specified
832      * by the SocketAddress {@code remoteAddr} with the specified timeout. The
833      * connecting method will block until the connection is established or an
834      * error occurred.
835      *
836      * @param remoteAddr
837      *            the address and port of the remote host to connect to.
838      * @param timeout
839      *            the timeout value in milliseconds or {@code 0} for an infinite
840      *            timeout.
841      * @throws IllegalArgumentException
842      *             if the given SocketAddress is invalid or not supported or the
843      *             timeout value is negative.
844      * @throws IOException
845      *             if the socket is already connected or an error occurs while
846      *             connecting.
847      */
connect(SocketAddress remoteAddr, int timeout)848     public void connect(SocketAddress remoteAddr, int timeout) throws IOException {
849         checkOpenAndCreate(true);
850         if (timeout < 0) {
851             throw new IllegalArgumentException("timeout < 0");
852         }
853         if (isConnected()) {
854             throw new SocketException("Already connected");
855         }
856         if (remoteAddr == null) {
857             throw new IllegalArgumentException("remoteAddr == null");
858         }
859 
860         if (!(remoteAddr instanceof InetSocketAddress)) {
861             throw new IllegalArgumentException("Remote address not an InetSocketAddress: " +
862                     remoteAddr.getClass());
863         }
864         InetSocketAddress inetAddr = (InetSocketAddress) remoteAddr;
865         InetAddress addr;
866         if ((addr = inetAddr.getAddress()) == null) {
867             throw new UnknownHostException("Host is unresolved: " + inetAddr.getHostName());
868         }
869         int port = inetAddr.getPort();
870 
871         checkDestination(addr, port);
872         synchronized (connectLock) {
873             try {
874                 if (!isBound()) {
875                     // socket already created at this point by earlier call or
876                     // checkOpenAndCreate this caused us to lose socket
877                     // options on create
878                     // impl.create(true);
879                     if (!usingSocks()) {
880                         impl.bind(Inet6Address.ANY, 0);
881                     }
882                     isBound = true;
883                 }
884                 impl.connect(remoteAddr, timeout);
885                 isConnected = true;
886                 cacheLocalAddress();
887             } catch (IOException e) {
888                 impl.close();
889                 throw e;
890             }
891         }
892     }
893 
894     /**
895      * Sets the Socket and its related SocketImpl state as if a successful connect() took place,
896      * without actually performing an OS connect().
897      *
898      * @hide internal use only
899      */
onConnect(InetAddress remoteAddress, int remotePort)900     public void onConnect(InetAddress remoteAddress, int remotePort) {
901         isConnected = true;
902         impl.onConnect(remoteAddress, remotePort);
903     }
904 
905     /**
906      * Returns whether the incoming channel of the socket has already been
907      * closed.
908      *
909      * @return {@code true} if reading from this socket is not possible anymore,
910      *         {@code false} otherwise.
911      */
isInputShutdown()912     public boolean isInputShutdown() {
913         return isInputShutdown;
914     }
915 
916     /**
917      * Returns whether the outgoing channel of the socket has already been
918      * closed.
919      *
920      * @return {@code true} if writing to this socket is not possible anymore,
921      *         {@code false} otherwise.
922      */
isOutputShutdown()923     public boolean isOutputShutdown() {
924         return isOutputShutdown;
925     }
926 
927     /**
928      * Sets this socket's {@link SocketOptions#SO_REUSEADDR} option.
929      */
setReuseAddress(boolean reuse)930     public void setReuseAddress(boolean reuse) throws SocketException {
931         checkOpenAndCreate(true);
932         impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(reuse));
933     }
934 
935     /**
936      * Returns this socket's {@link SocketOptions#SO_REUSEADDR} setting.
937      */
getReuseAddress()938     public boolean getReuseAddress() throws SocketException {
939         checkOpenAndCreate(true);
940         return (Boolean) impl.getOption(SocketOptions.SO_REUSEADDR);
941     }
942 
943     /**
944      * Sets this socket's {@link SocketOptions#SO_OOBINLINE} option.
945      */
setOOBInline(boolean oobinline)946     public void setOOBInline(boolean oobinline) throws SocketException {
947         checkOpenAndCreate(true);
948         impl.setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(oobinline));
949     }
950 
951     /**
952      * Returns this socket's {@link SocketOptions#SO_OOBINLINE} setting.
953      */
getOOBInline()954     public boolean getOOBInline() throws SocketException {
955         checkOpenAndCreate(true);
956         return (Boolean) impl.getOption(SocketOptions.SO_OOBINLINE);
957     }
958 
959     /**
960      * Sets this socket's {@link SocketOptions#IP_TOS} value for every packet sent by this socket.
961      */
setTrafficClass(int value)962     public void setTrafficClass(int value) throws SocketException {
963         checkOpenAndCreate(true);
964         if (value < 0 || value > 255) {
965             throw new IllegalArgumentException("Value doesn't fit in an unsigned byte: " + value);
966         }
967         impl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value));
968     }
969 
970     /**
971      * Returns this socket's {@see SocketOptions#IP_TOS} setting.
972      */
getTrafficClass()973     public int getTrafficClass() throws SocketException {
974         checkOpenAndCreate(true);
975         return (Integer) impl.getOption(SocketOptions.IP_TOS);
976     }
977 
978     /**
979      * Sends the given single byte data which is represented by the lowest octet
980      * of {@code value} as "TCP urgent data".
981      *
982      * @param value
983      *            the byte of urgent data to be sent.
984      * @throws IOException
985      *             if an error occurs while sending urgent data.
986      */
sendUrgentData(int value)987     public void sendUrgentData(int value) throws IOException {
988         impl.sendUrgentData(value);
989     }
990 
991     /**
992      * Set the appropriate flags for a socket created by {@code
993      * ServerSocket.accept()}.
994      *
995      * @see ServerSocket#implAccept
996      */
accepted()997     void accepted() throws SocketException {
998         isCreated = isBound = isConnected = true;
999         cacheLocalAddress();
1000     }
1001 
cacheLocalAddress()1002     private void cacheLocalAddress() throws SocketException {
1003         this.localAddress = IoBridge.getSocketLocalAddress(impl.fd);
1004     }
1005 
1006     /**
1007      * Returns this socket's {@code SocketChannel}, if one exists. A channel is
1008      * available only if this socket wraps a channel. (That is, you can go from a
1009      * channel to a socket and back again, but you can't go from an arbitrary socket to a channel.)
1010      * In practice, this means that the socket must have been created by
1011      * {@link java.nio.channels.ServerSocketChannel#accept} or
1012      * {@link java.nio.channels.SocketChannel#open}.
1013      */
getChannel()1014     public SocketChannel getChannel() {
1015         return null;
1016     }
1017 
1018     /**
1019      * @hide internal use only
1020      */
getFileDescriptor$()1021     public FileDescriptor getFileDescriptor$() {
1022         return impl.fd;
1023     }
1024 
1025     /**
1026      * Sets performance preferences for connectionTime, latency and bandwidth.
1027      *
1028      * <p>This method does currently nothing.
1029      *
1030      * @param connectionTime
1031      *            the value representing the importance of a short connecting
1032      *            time.
1033      * @param latency
1034      *            the value representing the importance of low latency.
1035      * @param bandwidth
1036      *            the value representing the importance of high bandwidth.
1037      */
setPerformancePreferences(int connectionTime, int latency, int bandwidth)1038     public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
1039         // Our socket implementation only provide one protocol: TCP/IP, so
1040         // we do nothing for this method
1041     }
1042 }
1043