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