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