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