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