PageRenderTime 59ms CodeModel.GetById 20ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/classpath/java/net/Socket.java

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