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