1 /* Socket.java -- Client socket implementation
2    Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2006, 2007
3    Free Software Foundation, Inc.
4 
5 This file is part of GNU Classpath.
6 
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11 
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING.  If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
21 
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library.  Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
26 
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module.  An independent module is a module which is not derived from
34 or based on this library.  If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so.  If you do not wish to do so, delete this
37 exception statement from your version. */
38 
39 package java.net;
40 
41 import gnu.java.net.PlainSocketImpl;
42 
43 import java.io.IOException;
44 import java.io.InputStream;
45 import java.io.OutputStream;
46 import java.nio.channels.IllegalBlockingModeException;
47 import java.nio.channels.SocketChannel;
48 
49 
50 /* Written using on-line Java Platform 1.2 API Specification.
51  * Status:  I believe all methods are implemented.
52  */
53 
54 /**
55  * This class models a client site socket.  A socket is a TCP/IP endpoint
56  * for network communications conceptually similar to a file handle.
57  * <p>
58  * This class does not actually do any work.  Instead, it redirects all of
59  * its calls to a socket implementation object which implements the
60  * <code>SocketImpl</code> interface.  The implementation class is
61  * instantiated by factory class that implements the
62  * <code>SocketImplFactory interface</code>.  A default
63  * factory is provided, however the factory may be set by a call to
64  * the <code>setSocketImplFactory</code> method.  Note that this may only be
65  * done once per virtual machine.  If a subsequent attempt is made to set the
66  * factory, a <code>SocketException</code> will be thrown.
67  *
68  * @author Aaron M. Renn (arenn@urbanophile.com)
69  * @author Per Bothner (bothner@cygnus.com)
70  */
71 public class Socket
72 {
73   /**
74    * This is the user SocketImplFactory for this class.  If this variable is
75    * null, a default factory is used.
76    */
77   static SocketImplFactory factory;
78 
79   /**
80    * The implementation object to which calls are redirected
81    */
82   // package-private because ServerSocket.implAccept() needs to access it.
83   SocketImpl impl;
84 
85   /**
86    * True if impl.create() has been called.
87    */
88   // package-private because ServerSocket.implAccept() needs to access it.
89   boolean implCreated;
90 
91   /**
92    * True if the socket is bound.
93    * Package private so it can be set from ServerSocket when accept is called.
94    */
95   boolean bound;
96 
97   /**
98    * True if input is shutdown.
99    */
100   private boolean inputShutdown;
101 
102   /**
103    * True if output is shutdown.
104    */
105   private boolean outputShutdown;
106 
107   /**
108    * Initializes a new instance of <code>Socket</code> object without
109    * connecting to a remote host.  This useful for subclasses of socket that
110    * might want this behavior.
111    *
112    * @specnote This constructor is public since JDK 1.4
113    * @since 1.1
114    */
Socket()115   public Socket()
116   {
117     if (factory != null)
118       impl = factory.createSocketImpl();
119     else
120       impl = new PlainSocketImpl();
121   }
122 
123   /**
124    * Initializes a new instance of <code>Socket</code> object without
125    * connecting to a remote host.  This is useful for subclasses of socket
126    * that might want this behavior.
127    * <p>
128    * Additionally, this socket will be created using the supplied
129    * implementation class instead the default class or one returned by a
130    * factory.  If this value is <code>null</code>, the default Socket
131    * implementation is used.
132    *
133    * @param impl The <code>SocketImpl</code> to use for this
134    *             <code>Socket</code>
135    *
136    * @exception SocketException If an error occurs
137    *
138    * @since 1.1
139    */
Socket(SocketImpl impl)140   protected Socket(SocketImpl impl) throws SocketException
141   {
142     if (impl == null)
143       this.impl = new PlainSocketImpl();
144     else
145       this.impl = impl;
146   }
147 
148   /**
149    * Initializes a new instance of <code>Socket</code> and connects to the
150    * hostname and port specified as arguments.
151    *
152    * @param host The name of the host to connect to
153    * @param port The port number to connect to
154    *
155    * @exception UnknownHostException If the hostname cannot be resolved to a
156    * network address.
157    * @exception IOException If an error occurs
158    * @exception SecurityException If a security manager exists and its
159    * checkConnect method doesn't allow the operation
160    */
Socket(String host, int port)161   public Socket(String host, int port)
162     throws UnknownHostException, IOException
163   {
164     this(InetAddress.getByName(host), port, null, 0, true);
165   }
166 
167   /**
168    * Initializes a new instance of <code>Socket</code> and connects to the
169    * address and port number specified as arguments.
170    *
171    * @param address The address to connect to
172    * @param port The port number to connect to
173    *
174    * @exception IOException If an error occurs
175    * @exception SecurityException If a security manager exists and its
176    * checkConnect method doesn't allow the operation
177    */
Socket(InetAddress address, int port)178   public Socket(InetAddress address, int port) throws IOException
179   {
180     this(address, port, null, 0, true);
181   }
182 
183   /**
184    * Initializes a new instance of <code>Socket</code> that connects to the
185    * named host on the specified port and binds to the specified local address
186    * and port.
187    *
188    * @param host The name of the remote host to connect to.
189    * @param port The remote port to connect to.
190    * @param localAddr The local address to bind to.
191    * @param localPort The local port to bind to.
192    *
193    * @exception SecurityException If the <code>SecurityManager</code>
194    * exists and does not allow a connection to the specified host/port or
195    * binding to the specified local host/port.
196    * @exception IOException If a connection error occurs.
197    *
198    * @since 1.1
199    */
Socket(String host, int port, InetAddress localAddr, int localPort)200   public Socket(String host, int port, InetAddress localAddr, int localPort)
201     throws IOException
202   {
203     this(InetAddress.getByName(host), port, localAddr, localPort, true);
204   }
205 
206   /**
207    * Initializes a new instance of <code>Socket</code> and connects to the
208    * address and port number specified as arguments, plus binds to the
209    * specified local address and port.
210    *
211    * @param address The remote address to connect to
212    * @param port The remote port to connect to
213    * @param localAddr The local address to connect to
214    * @param localPort The local port to connect to
215    *
216    * @exception IOException If an error occurs
217    * @exception SecurityException If a security manager exists and its
218    * checkConnect method doesn't allow the operation
219    *
220    * @since 1.1
221    */
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)222   public Socket(InetAddress address, int port, InetAddress localAddr,
223                 int localPort) throws IOException
224   {
225     this(address, port, localAddr, localPort, true);
226   }
227 
228   /**
229    * Initializes a new instance of <code>Socket</code> and connects to the
230    * hostname and port specified as arguments.  If the stream argument is set
231    * to <code>true</code>, then a stream socket is created.  If it is
232    * <code>false</code>, a datagram socket is created.
233    *
234    * @param host The name of the host to connect to
235    * @param port The port to connect to
236    * @param stream <code>true</code> for a stream socket, <code>false</code>
237    * for a datagram socket
238    *
239    * @exception IOException If an error occurs
240    * @exception SecurityException If a security manager exists and its
241    * checkConnect method doesn't allow the operation
242    *
243    * @deprecated Use the <code>DatagramSocket</code> class to create
244    * datagram oriented sockets.
245    */
Socket(String host, int port, boolean stream)246   public Socket(String host, int port, boolean stream)
247     throws IOException
248   {
249     this(InetAddress.getByName(host), port, null, 0, stream);
250   }
251 
252   /**
253    * Initializes a new instance of <code>Socket</code> and connects to the
254    * address and port number specified as arguments.  If the stream param is
255    * <code>true</code>, a stream socket will be created, otherwise a datagram
256    * socket is created.
257    *
258    * @param host The address to connect to
259    * @param port The port number to connect to
260    * @param stream <code>true</code> to create a stream socket,
261    * <code>false</code> to create a datagram socket.
262    *
263    * @exception IOException If an error occurs
264    * @exception SecurityException If a security manager exists and its
265    * checkConnect method doesn't allow the operation
266    *
267    * @deprecated Use the <code>DatagramSocket</code> class to create
268    * datagram oriented sockets.
269    */
Socket(InetAddress host, int port, boolean stream)270   public Socket(InetAddress host, int port, boolean stream)
271     throws IOException
272   {
273     this(host, port, null, 0, stream);
274   }
275 
276   /**
277    * This constructor is where the real work takes place.  Connect to the
278    * specified address and port.  Use default local values if not specified,
279    * otherwise use the local host and port passed in.  Create as stream or
280    * datagram based on "stream" argument.
281    * <p>
282    *
283    * @param raddr The remote address to connect to
284    * @param rport The remote port to connect to
285    * @param laddr The local address to connect to
286    * @param lport The local port to connect to
287    * @param stream true for a stream socket, false for a datagram socket
288    *
289    * @exception IOException If an error occurs
290    * @exception SecurityException If a security manager exists and its
291    * checkConnect method doesn't allow the operation
292    */
Socket(InetAddress raddr, int rport, InetAddress laddr, int lport, boolean stream)293   private Socket(InetAddress raddr, int rport, InetAddress laddr, int lport,
294                  boolean stream) throws IOException
295   {
296     this();
297 
298     SecurityManager sm = System.getSecurityManager();
299     if (sm != null)
300       sm.checkConnect(raddr.getHostAddress(), rport);
301 
302     // bind socket
303     SocketAddress bindaddr =
304       laddr == null ? null : new InetSocketAddress(laddr, lport);
305     bind(bindaddr);
306 
307     // Connect socket in case of Exceptions we must close the socket
308     // because an exception in the constructor means that the caller will
309     // not have a reference to this instance.
310     // Note: You may have the idea that the exception treatment
311     // should be moved into connect() but there is a Mauve test which
312     // shows that a failed connect should not close the socket.
313     try
314       {
315         connect(new InetSocketAddress(raddr, rport));
316       }
317     catch (IOException ioe)
318       {
319         impl.close();
320         throw ioe;
321       }
322     catch (RuntimeException re)
323       {
324         impl.close();
325         throw re;
326       }
327 
328     // FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
329     // i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
330     // that default.  JDK 1.2 doc infers not to do a bind.
331   }
332 
getImpl()333   private SocketImpl getImpl() throws SocketException
334   {
335     if (! implCreated)
336       {
337         try
338           {
339             impl.create(true);
340           }
341         catch (IOException x)
342           {
343             throw (SocketException) new SocketException().initCause(x);
344           }
345         implCreated = true;
346       }
347     return impl;
348   }
349 
350   /**
351    * Binds the socket to the given local address/port
352    *
353    * @param bindpoint The address/port to bind to
354    *
355    * @exception IOException If an error occurs
356    * @exception SecurityException If a security manager exists and its
357    * checkConnect method doesn't allow the operation
358    * @exception IllegalArgumentException If the address type is not supported
359    *
360    * @since 1.4
361    */
bind(SocketAddress bindpoint)362   public void bind(SocketAddress bindpoint) throws IOException
363   {
364     if (isClosed())
365       throw new SocketException("socket is closed");
366 
367     // XXX: JDK 1.4.1 API documentation says that if bindpoint is null the
368     // socket will be bound to an ephemeral port and a valid local address.
369     if (bindpoint == null)
370       bindpoint = new InetSocketAddress(InetAddress.ANY_IF, 0);
371 
372     if (! (bindpoint instanceof InetSocketAddress))
373       throw new IllegalArgumentException();
374 
375     InetSocketAddress tmp = (InetSocketAddress) bindpoint;
376 
377     // bind to address/port
378     try
379       {
380         getImpl().bind(tmp.getAddress(), tmp.getPort());
381         bound = true;
382       }
383     catch (IOException exception)
384       {
385         close();
386         throw exception;
387       }
388     catch (RuntimeException exception)
389       {
390         close();
391         throw exception;
392       }
393     catch (Error error)
394       {
395         close();
396         throw error;
397       }
398   }
399 
400   /**
401    * Connects the socket with a remote address.
402    *
403    * @param endpoint The address to connect to
404    *
405    * @exception IOException If an error occurs
406    * @exception IllegalArgumentException If the addess type is not supported
407    * @exception IllegalBlockingModeException If this socket has an associated
408    * channel, and the channel is in non-blocking mode
409    *
410    * @since 1.4
411    */
connect(SocketAddress endpoint)412   public void connect(SocketAddress endpoint) throws IOException
413   {
414     connect(endpoint, 0);
415   }
416 
417   /**
418    * Connects the socket with a remote address. A timeout of zero is
419    * interpreted as an infinite timeout. The connection will then block
420    * until established or an error occurs.
421    *
422    * @param endpoint The address to connect to
423    * @param timeout The length of the timeout in milliseconds, or
424    * 0 to indicate no timeout.
425    *
426    * @exception IOException If an error occurs
427    * @exception IllegalArgumentException If the address type is not supported
428    * @exception IllegalBlockingModeException If this socket has an associated
429    * channel, and the channel is in non-blocking mode
430    * @exception SocketTimeoutException If the timeout is reached
431    * @throws SecurityException if the SocketAddress is an {@link InetSocketAddress}
432    *                           and a security manager is present which does not
433    *                           allow connections on the given host and port.
434    * @since 1.4
435    */
connect(SocketAddress endpoint, int timeout)436   public void connect(SocketAddress endpoint, int timeout)
437     throws IOException
438   {
439     if (isClosed())
440       throw new SocketException("socket is closed");
441 
442     if (! (endpoint instanceof InetSocketAddress))
443       throw new IllegalArgumentException("unsupported address type");
444 
445     SecurityManager sm = System.getSecurityManager();
446     if (sm != null)
447       {
448         InetSocketAddress inetAddr = (InetSocketAddress) endpoint;
449         sm.checkConnect(inetAddr.getHostName(), inetAddr.getPort());
450       }
451 
452     // The Sun spec says that if we have an associated channel and
453     // it is in non-blocking mode, we throw an IllegalBlockingModeException.
454     // However, in our implementation if the channel itself initiated this
455     // operation, then we must honor it regardless of its blocking mode.
456     if (getChannel() != null && ! getChannel().isBlocking()
457         && ! ((PlainSocketImpl) getImpl()).isInChannelOperation())
458       throw new IllegalBlockingModeException();
459 
460     if (! isBound())
461       bind(null);
462 
463     getImpl().connect(endpoint, timeout);
464   }
465 
466   /**
467    * Returns the address of the remote end of the socket.  If this socket
468    * is not connected, then <code>null</code> is returned.
469    *
470    * @return The remote address this socket is connected to
471    */
getInetAddress()472   public InetAddress getInetAddress()
473   {
474     if (! isConnected())
475       return null;
476 
477     try
478       {
479         return getImpl().getInetAddress();
480       }
481     catch (SocketException e)
482       {
483         // This cannot happen as we are connected.
484       }
485 
486     return null;
487   }
488 
489   /**
490    * Returns the local address to which this socket is bound.  If this socket
491    * is not connected, then a wildcard address, for which
492    * @see InetAddress#isAnyLocalAddress() is <code>true</code>, is returned.
493    *
494    * @return The local address
495    *
496    * @since 1.1
497    */
getLocalAddress()498   public InetAddress getLocalAddress()
499   {
500     if (! isBound())
501       return InetAddress.ANY_IF;
502 
503     InetAddress addr = null;
504 
505     if (impl instanceof PlainSocketImpl)
506       addr = ((PlainSocketImpl) impl).getLocalAddress().getAddress();
507 
508     if (addr == null)
509       {
510         try
511           {
512             addr = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
513           }
514         catch (SocketException e)
515           {
516             // (hopefully) shouldn't happen
517             // throw new java.lang.InternalError
518             //      ("Error in PlainSocketImpl.getOption");
519             return null;
520           }
521       }
522 
523     // FIXME: According to libgcj, checkConnect() is supposed to be called
524     // before performing this operation.  Problems: 1) We don't have the
525     // addr until after we do it, so we do a post check.  2). The docs I
526     // see don't require this in the Socket case, only DatagramSocket, but
527     // we'll assume they mean both.
528     SecurityManager sm = System.getSecurityManager();
529     if (sm != null)
530       sm.checkConnect(addr.getHostName(), getLocalPort());
531 
532     return addr;
533   }
534 
535   /**
536    * Returns the port number of the remote end of the socket connection.  If
537    * this socket is not connected, then 0 is returned.
538    *
539    * @return The remote port this socket is connected to
540    */
getPort()541   public int getPort()
542   {
543     if (! isConnected())
544       return 0;
545 
546     try
547       {
548         return getImpl().getPort();
549       }
550     catch (SocketException e)
551       {
552         // This cannot happen as we are connected.
553       }
554 
555     return 0;
556   }
557 
558   /**
559    * Returns the local port number to which this socket is bound.  If this
560    * socket is not connected, then -1 is returned.
561    *
562    * @return The local port
563    */
getLocalPort()564   public int getLocalPort()
565   {
566     if (! isBound())
567       return -1;
568 
569     try
570       {
571         if (getImpl() != null)
572           return getImpl().getLocalPort();
573       }
574     catch (SocketException e)
575       {
576         // This cannot happen as we are bound.
577       }
578 
579     return -1;
580   }
581 
582   /**
583    * Returns local socket address.
584    *
585    * @return the local socket address, null if not bound
586    *
587    * @since 1.4
588    */
getLocalSocketAddress()589   public SocketAddress getLocalSocketAddress()
590   {
591     if (! isBound())
592       return null;
593 
594     InetAddress addr = getLocalAddress();
595 
596     try
597       {
598         return new InetSocketAddress(addr, getImpl().getLocalPort());
599       }
600     catch (SocketException e)
601       {
602         // This cannot happen as we are bound.
603         return null;
604       }
605   }
606 
607   /**
608    * Returns the remote socket address.
609    *
610    * @return the remote socket address, null of not connected
611    *
612    * @since 1.4
613    */
getRemoteSocketAddress()614   public SocketAddress getRemoteSocketAddress()
615   {
616     if (! isConnected())
617       return null;
618 
619     try
620       {
621         return new InetSocketAddress(getImpl().getInetAddress(),
622                                      getImpl().getPort());
623       }
624     catch (SocketException e)
625       {
626         // This cannot happen as we are connected.
627         return null;
628       }
629   }
630 
631   /**
632    * Returns an InputStream for reading from this socket.
633    *
634    * @return The InputStream object
635    *
636    * @exception IOException If an error occurs or Socket is not connected
637    */
getInputStream()638   public InputStream getInputStream() throws IOException
639   {
640     if (isClosed())
641       throw new SocketException("socket is closed");
642 
643     if (! isConnected())
644       throw new IOException("not connected");
645 
646     return getImpl().getInputStream();
647   }
648 
649   /**
650    * Returns an OutputStream for writing to this socket.
651    *
652    * @return The OutputStream object
653    *
654    * @exception IOException If an error occurs or Socket is not connected
655    */
getOutputStream()656   public OutputStream getOutputStream() throws IOException
657   {
658     if (isClosed())
659       throw new SocketException("socket is closed");
660 
661     if (! isConnected())
662       throw new IOException("not connected");
663 
664     return getImpl().getOutputStream();
665   }
666 
667   /**
668    * Sets the TCP_NODELAY option on the socket.
669    *
670    * @param on true to enable, false to disable
671    *
672    * @exception SocketException If an error occurs or Socket is not connected
673    *
674    * @since 1.1
675    */
setTcpNoDelay(boolean on)676   public void setTcpNoDelay(boolean on) throws SocketException
677   {
678     if (isClosed())
679       throw new SocketException("socket is closed");
680 
681     getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
682   }
683 
684   /**
685    * Tests whether or not the TCP_NODELAY option is set on the socket.
686    * Returns true if enabled, false if disabled. When on it disables the
687    * Nagle algorithm which means that packets are always send immediatly and
688    * never merged together to reduce network trafic.
689    *
690    * @return Whether or not TCP_NODELAY is set
691    *
692    * @exception SocketException If an error occurs or Socket not connected
693    *
694    * @since 1.1
695    */
getTcpNoDelay()696   public boolean getTcpNoDelay() throws SocketException
697   {
698     if (isClosed())
699       throw new SocketException("socket is closed");
700 
701     Object on = getImpl().getOption(SocketOptions.TCP_NODELAY);
702 
703     if (on instanceof Boolean)
704       return (((Boolean) on).booleanValue());
705     else
706       throw new SocketException("Internal Error");
707   }
708 
709   /**
710    * Sets the value of the SO_LINGER option on the socket.  If the
711    * SO_LINGER option is set on a socket and there is still data waiting to
712    * be sent when the socket is closed, then the close operation will block
713    * until either that data is delivered or until the timeout period
714    * expires.  The linger interval is specified in hundreths of a second
715    * (platform specific?)
716    *
717    * @param on true to enable SO_LINGER, false to disable
718    * @param linger The SO_LINGER timeout in hundreths of a second or -1 if
719    * SO_LINGER not set.
720    *
721    * @exception SocketException If an error occurs or Socket not connected
722    * @exception IllegalArgumentException If linger is negative
723    *
724    * @since 1.1
725    */
setSoLinger(boolean on, int linger)726   public void setSoLinger(boolean on, int linger) throws SocketException
727   {
728     if (isClosed())
729       throw new SocketException("socket is closed");
730 
731     if (on)
732       {
733         if (linger < 0)
734           throw new IllegalArgumentException("SO_LINGER must be >= 0");
735 
736         if (linger > 65535)
737           linger = 65535;
738 
739         getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(linger));
740       }
741     else
742       getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(-1));
743   }
744 
745   /**
746    * Returns the value of the SO_LINGER option on the socket.  If the
747    * SO_LINGER option is set on a socket and there is still data waiting to
748    * be sent when the socket is closed, then the close operation will block
749    * until either that data is delivered or until the timeout period
750    * expires.  This method either returns the timeouts (in hundredths of
751    * of a second (platform specific?)) if SO_LINGER is set, or -1 if
752    * SO_LINGER is not set.
753    *
754    * @return The SO_LINGER timeout in hundreths of a second or -1
755    * if SO_LINGER not set
756    *
757    * @exception SocketException If an error occurs or Socket is not connected
758    *
759    * @since 1.1
760    */
getSoLinger()761   public int getSoLinger() throws SocketException
762   {
763     if (isClosed())
764       throw new SocketException("socket is closed");
765 
766     Object linger = getImpl().getOption(SocketOptions.SO_LINGER);
767 
768     if (linger instanceof Integer)
769       return (((Integer) linger).intValue());
770     else
771       return -1;
772   }
773 
774   /**
775    * Sends urgent data through the socket
776    *
777    * @param data The data to send.
778    * Only the lowest eight bits of data are sent
779    *
780    * @exception IOException If an error occurs
781    *
782    * @since 1.4
783    */
sendUrgentData(int data)784   public void sendUrgentData(int data) throws IOException
785   {
786     if (isClosed())
787       throw new SocketException("socket is closed");
788 
789     getImpl().sendUrgentData(data);
790   }
791 
792   /**
793    * Enables/disables the SO_OOBINLINE option
794    *
795    * @param on True if SO_OOBLINE should be enabled
796    *
797    * @exception SocketException If an error occurs
798    *
799    * @since 1.4
800    */
setOOBInline(boolean on)801   public void setOOBInline(boolean on) throws SocketException
802   {
803     if (isClosed())
804       throw new SocketException("socket is closed");
805 
806     getImpl().setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(on));
807   }
808 
809   /**
810    * Returns the current setting of the SO_OOBINLINE option for this socket
811    *
812    * @return True if SO_OOBINLINE is set, false otherwise.
813    *
814    * @exception SocketException If an error occurs
815    *
816    * @since 1.4
817    */
getOOBInline()818   public boolean getOOBInline() throws SocketException
819   {
820     if (isClosed())
821       throw new SocketException("socket is closed");
822 
823     Object buf = getImpl().getOption(SocketOptions.SO_OOBINLINE);
824 
825     if (buf instanceof Boolean)
826       return (((Boolean) buf).booleanValue());
827     else
828       throw new SocketException("Internal Error: Unexpected type");
829   }
830 
831   /**
832    * Sets the value of the SO_TIMEOUT option on the socket.  If this value
833    * is set, and an read/write is performed that does not complete within
834    * the timeout period, a short count is returned (or an EWOULDBLOCK signal
835    * would be sent in Unix if no data had been read).  A value of 0 for
836    * this option implies that there is no timeout (ie, operations will
837    * block forever).  On systems that have separate read and write timeout
838    * values, this method returns the read timeout.  This
839    * value is in milliseconds.
840    *
841    * @param timeout The length of the timeout in milliseconds, or
842    * 0 to indicate no timeout.
843    *
844    * @exception SocketException If an error occurs or Socket not connected
845    *
846    * @since 1.1
847    */
setSoTimeout(int timeout)848   public synchronized void setSoTimeout(int timeout) throws SocketException
849   {
850     if (isClosed())
851       throw new SocketException("socket is closed");
852 
853     if (timeout < 0)
854       throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");
855 
856     getImpl().setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
857   }
858 
859   /**
860    * Returns the value of the SO_TIMEOUT option on the socket.  If this value
861    * is set, and an read/write is performed that does not complete within
862    * the timeout period, a short count is returned (or an EWOULDBLOCK signal
863    * would be sent in Unix if no data had been read).  A value of 0 for
864    * this option implies that there is no timeout (ie, operations will
865    * block forever).  On systems that have separate read and write timeout
866    * values, this method returns the read timeout.  This
867    * value is in thousandths of a second (implementation specific?).
868    *
869    * @return The length of the timeout in thousandth's of a second or 0
870    * if not set
871    *
872    * @exception SocketException If an error occurs or Socket not connected
873    *
874    * @since 1.1
875    */
getSoTimeout()876   public synchronized int getSoTimeout() throws SocketException
877   {
878     if (isClosed())
879       throw new SocketException("socket is closed");
880 
881     Object timeout = getImpl().getOption(SocketOptions.SO_TIMEOUT);
882     if (timeout instanceof Integer)
883       return (((Integer) timeout).intValue());
884     else
885       return 0;
886   }
887 
888   /**
889    * This method sets the value for the system level socket option
890    * SO_SNDBUF to the specified value.  Note that valid values for this
891    * option are specific to a given operating system.
892    *
893    * @param size The new send buffer size.
894    *
895    * @exception SocketException If an error occurs or Socket not connected
896    * @exception IllegalArgumentException If size is 0 or negative
897    *
898    * @since 1.2
899    */
setSendBufferSize(int size)900   public void setSendBufferSize(int size) throws SocketException
901   {
902     if (isClosed())
903       throw new SocketException("socket is closed");
904 
905     if (size <= 0)
906       throw new IllegalArgumentException("SO_SNDBUF value must be > 0");
907 
908     getImpl().setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
909   }
910 
911   /**
912    * This method returns the value of the system level socket option
913    * SO_SNDBUF, which is used by the operating system to tune buffer
914    * sizes for data transfers.
915    *
916    * @return The send buffer size.
917    *
918    * @exception SocketException If an error occurs or socket not connected
919    *
920    * @since 1.2
921    */
getSendBufferSize()922   public int getSendBufferSize() throws SocketException
923   {
924     if (isClosed())
925       throw new SocketException("socket is closed");
926 
927     Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF);
928 
929     if (buf instanceof Integer)
930       return (((Integer) buf).intValue());
931     else
932       throw new SocketException("Internal Error: Unexpected type");
933   }
934 
935   /**
936    * This method sets the value for the system level socket option
937    * SO_RCVBUF to the specified value.  Note that valid values for this
938    * option are specific to a given operating system.
939    *
940    * @param size The new receive buffer size.
941    *
942    * @exception SocketException If an error occurs or Socket is not connected
943    * @exception IllegalArgumentException If size is 0 or negative
944    *
945    * @since 1.2
946    */
setReceiveBufferSize(int size)947   public void setReceiveBufferSize(int size) throws SocketException
948   {
949     if (isClosed())
950       throw new SocketException("socket is closed");
951 
952     if (size <= 0)
953       throw new IllegalArgumentException("SO_RCVBUF value must be > 0");
954 
955     getImpl().setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
956   }
957 
958   /**
959    * This method returns the value of the system level socket option
960    * SO_RCVBUF, which is used by the operating system to tune buffer
961    * sizes for data transfers.
962    *
963    * @return The receive buffer size.
964    *
965    * @exception SocketException If an error occurs or Socket is not connected
966    *
967    * @since 1.2
968    */
getReceiveBufferSize()969   public int getReceiveBufferSize() throws SocketException
970   {
971     if (isClosed())
972       throw new SocketException("socket is closed");
973 
974     Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF);
975 
976     if (buf instanceof Integer)
977       return (((Integer) buf).intValue());
978     else
979       throw new SocketException("Internal Error: Unexpected type");
980   }
981 
982   /**
983    * This method sets the value for the socket level socket option
984    * SO_KEEPALIVE.
985    *
986    * @param on True if SO_KEEPALIVE should be enabled
987    *
988    * @exception SocketException If an error occurs or Socket is not connected
989    *
990    * @since 1.3
991    */
setKeepAlive(boolean on)992   public void setKeepAlive(boolean on) throws SocketException
993   {
994     if (isClosed())
995       throw new SocketException("socket is closed");
996 
997     getImpl().setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(on));
998   }
999 
1000   /**
1001    * This method returns the value of the socket level socket option
1002    * SO_KEEPALIVE.
1003    *
1004    * @return The setting
1005    *
1006    * @exception SocketException If an error occurs or Socket is not connected
1007    *
1008    * @since 1.3
1009    */
getKeepAlive()1010   public boolean getKeepAlive() throws SocketException
1011   {
1012     if (isClosed())
1013       throw new SocketException("socket is closed");
1014 
1015     Object buf = getImpl().getOption(SocketOptions.SO_KEEPALIVE);
1016 
1017     if (buf instanceof Boolean)
1018       return (((Boolean) buf).booleanValue());
1019     else
1020       throw new SocketException("Internal Error: Unexpected type");
1021   }
1022 
1023   /**
1024    * Closes the socket.
1025    *
1026    * @exception IOException If an error occurs
1027    */
close()1028   public synchronized void close() throws IOException
1029   {
1030     if (isClosed())
1031       return;
1032 
1033     impl.close();
1034     impl = null;
1035   }
1036 
1037   /**
1038    * Converts this <code>Socket</code> to a <code>String</code>.
1039    *
1040    * @return The <code>String</code> representation of this <code>Socket</code>
1041    */
toString()1042   public String toString()
1043   {
1044     try
1045       {
1046         if (isConnected())
1047           return (super.toString()
1048                   + " [addr=" + getImpl().getInetAddress() + ",port="
1049                   + getImpl().getPort() + ",localport="
1050                   + getImpl().getLocalPort() + "]");
1051       }
1052     catch (SocketException e)
1053       {
1054         // This cannot happen as we are connected.
1055       }
1056 
1057     return super.toString() + " [unconnected]";
1058   }
1059 
1060   /**
1061    * Sets the <code>SocketImplFactory</code>.  This may be done only once per
1062    * virtual machine.  Subsequent attempts will generate a
1063    * <code>SocketException</code>.  Note that a <code>SecurityManager</code>
1064    * check is made prior to setting the factory.  If
1065    * insufficient privileges exist to set the factory, then an
1066    * <code>IOException</code> will be thrown.
1067    *
1068    * @param fac the factory to set
1069    *
1070    * @exception SecurityException If the <code>SecurityManager</code> does
1071    * not allow this operation.
1072    * @exception SocketException If the SocketImplFactory is already defined
1073    * @exception IOException If any other error occurs
1074    */
setSocketImplFactory(SocketImplFactory fac)1075   public static synchronized void setSocketImplFactory(SocketImplFactory fac)
1076     throws IOException
1077   {
1078     // See if already set
1079     if (factory != null)
1080       throw new SocketException("SocketImplFactory already defined");
1081 
1082     // Check permissions
1083     SecurityManager sm = System.getSecurityManager();
1084     if (sm != null)
1085       sm.checkSetFactory();
1086 
1087     if (fac == null)
1088       throw new SocketException("SocketImplFactory cannot be null");
1089 
1090     factory = fac;
1091   }
1092 
1093   /**
1094    * Closes the input side of the socket stream.
1095    *
1096    * @exception IOException If an error occurs.
1097    *
1098    * @since 1.3
1099    */
shutdownInput()1100   public void shutdownInput() throws IOException
1101   {
1102     if (isClosed())
1103       throw new SocketException("socket is closed");
1104 
1105     getImpl().shutdownInput();
1106     inputShutdown = true;
1107   }
1108 
1109   /**
1110    * Closes the output side of the socket stream.
1111    *
1112    * @exception IOException If an error occurs.
1113    *
1114    * @since 1.3
1115    */
shutdownOutput()1116   public void shutdownOutput() throws IOException
1117   {
1118     if (isClosed())
1119       throw new SocketException("socket is closed");
1120 
1121     getImpl().shutdownOutput();
1122     outputShutdown = true;
1123   }
1124 
1125   /**
1126    * Returns the socket channel associated with this socket.
1127    *
1128    * @return the associated socket channel,
1129    * null if no associated channel exists
1130    *
1131    * @since 1.4
1132    */
getChannel()1133   public SocketChannel getChannel()
1134   {
1135     return null;
1136   }
1137 
1138   /**
1139    * Checks if the SO_REUSEADDR option is enabled
1140    *
1141    * @return True if SO_REUSEADDR is set, false otherwise.
1142    *
1143    * @exception SocketException If an error occurs
1144    *
1145    * @since 1.4
1146    */
getReuseAddress()1147   public boolean getReuseAddress() throws SocketException
1148   {
1149     if (isClosed())
1150       throw new SocketException("socket is closed");
1151 
1152     Object reuseaddr = getImpl().getOption(SocketOptions.SO_REUSEADDR);
1153 
1154     if (! (reuseaddr instanceof Boolean))
1155       throw new SocketException("Internal Error");
1156 
1157     return ((Boolean) reuseaddr).booleanValue();
1158   }
1159 
1160   /**
1161    * Enables/Disables the SO_REUSEADDR option
1162    *
1163    * @param reuseAddress true if SO_REUSEADDR should be enabled,
1164    * false otherwise
1165    *
1166    * @exception SocketException If an error occurs
1167    *
1168    * @since 1.4
1169    */
setReuseAddress(boolean reuseAddress)1170   public void setReuseAddress(boolean reuseAddress) throws SocketException
1171   {
1172     if (isClosed())
1173       throw new SocketException("socket is closed");
1174 
1175     getImpl().setOption(SocketOptions.SO_REUSEADDR,
1176                         Boolean.valueOf(reuseAddress));
1177   }
1178 
1179   /**
1180    * Returns the current traffic class
1181    *
1182    * @return The current traffic class.
1183    *
1184    * @exception SocketException If an error occurs
1185    *
1186    * @see Socket#setTrafficClass(int tc)
1187    *
1188    * @since 1.4
1189    */
getTrafficClass()1190   public int getTrafficClass() throws SocketException
1191   {
1192     if (isClosed())
1193       throw new SocketException("socket is closed");
1194 
1195     Object obj = getImpl().getOption(SocketOptions.IP_TOS);
1196 
1197     if (obj instanceof Integer)
1198       return ((Integer) obj).intValue();
1199     else
1200       throw new SocketException("Unexpected type");
1201   }
1202 
1203   /**
1204    * Sets the traffic class value
1205    *
1206    * @param tc The traffic class
1207    *
1208    * @exception SocketException If an error occurs
1209    * @exception IllegalArgumentException If tc value is illegal
1210    *
1211    * @see Socket#getTrafficClass()
1212    *
1213    * @since 1.4
1214    */
setTrafficClass(int tc)1215   public void setTrafficClass(int tc) throws SocketException
1216   {
1217     if (isClosed())
1218       throw new SocketException("socket is closed");
1219 
1220     if (tc < 0 || tc > 255)
1221       throw new IllegalArgumentException();
1222 
1223     getImpl().setOption(SocketOptions.IP_TOS, Integer.valueOf(tc));
1224   }
1225 
1226   /**
1227    * Checks if the socket is connected
1228    *
1229    * @return True if socket is connected, false otherwise.
1230    *
1231    * @since 1.4
1232    */
isConnected()1233   public boolean isConnected()
1234   {
1235     if (impl == null)
1236       return false;
1237 
1238     return impl.getInetAddress() != null;
1239   }
1240 
1241   /**
1242    * Checks if the socket is already bound.
1243    *
1244    * @return True if socket is bound, false otherwise.
1245    *
1246    * @since 1.4
1247    */
isBound()1248   public boolean isBound()
1249   {
1250     if (isClosed())
1251       return false;
1252     if (impl instanceof PlainSocketImpl)
1253       {
1254         InetSocketAddress addr = ((PlainSocketImpl) impl).getLocalAddress();
1255         return addr != null && addr.getAddress() != null;
1256       }
1257     return bound;
1258   }
1259 
1260   /**
1261    * Checks if the socket is closed.
1262    *
1263    * @return True if socket is closed, false otherwise.
1264    *
1265    * @since 1.4
1266    */
isClosed()1267   public boolean isClosed()
1268   {
1269     SocketChannel channel = getChannel();
1270 
1271     return impl == null || (channel != null && ! channel.isOpen());
1272   }
1273 
1274   /**
1275    * Checks if the socket's input stream is shutdown
1276    *
1277    * @return True if input is shut down.
1278    *
1279    * @since 1.4
1280    */
isInputShutdown()1281   public boolean isInputShutdown()
1282   {
1283     return inputShutdown;
1284   }
1285 
1286   /**
1287    * Checks if the socket's output stream is shutdown
1288    *
1289    * @return True if output is shut down.
1290    *
1291    * @since 1.4
1292    */
isOutputShutdown()1293   public boolean isOutputShutdown()
1294   {
1295     return outputShutdown;
1296   }
1297 }
1298