/* Socket.java -- Client socket implementation
   Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2006, 2007
   Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package java.net;

import gnu.java.net.PlainSocketImpl;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.IllegalBlockingModeException;
import java.nio.channels.SocketChannel;


/* Written using on-line Java Platform 1.2 API Specification.
 * Status:  I believe all methods are implemented.
 */

/**
 * This class models a client site socket.  A socket is a TCP/IP endpoint
 * for network communications conceptually similar to a file handle.
 * <p>
 * This class does not actually do any work.  Instead, it redirects all of
 * its calls to a socket implementation object which implements the
 * <code>SocketImpl</code> interface.  The implementation class is
 * instantiated by factory class that implements the
 * <code>SocketImplFactory interface</code>.  A default
 * factory is provided, however the factory may be set by a call to
 * the <code>setSocketImplFactory</code> method.  Note that this may only be
 * done once per virtual machine.  If a subsequent attempt is made to set the
 * factory, a <code>SocketException</code> will be thrown.
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @author Per Bothner (bothner@cygnus.com)
 */
public class Socket
{
  /**
   * This is the user SocketImplFactory for this class.  If this variable is
   * null, a default factory is used.
   */
  static SocketImplFactory factory;

  /**
   * The implementation object to which calls are redirected
   */
  // package-private because ServerSocket.implAccept() needs to access it.
  SocketImpl impl;

  /**
   * True if impl.create() has been called.
   */
  // package-private because ServerSocket.implAccept() needs to access it.
  boolean implCreated;

  /**
   * True if the socket is bound.
   * Package private so it can be set from ServerSocket when accept is called.
   */
  boolean bound;

  /**
   * True if input is shutdown.
   */
  private boolean inputShutdown;

  /**
   * True if output is shutdown.
   */
  private boolean outputShutdown;

  /**
   * Initializes a new instance of <code>Socket</code> object without
   * connecting to a remote host.  This useful for subclasses of socket that
   * might want this behavior.
   *
   * @specnote This constructor is public since JDK 1.4
   * @since 1.1
   */
  public Socket()
  {
    if (factory != null)
      impl = factory.createSocketImpl();
    else
      impl = new PlainSocketImpl();
  }

  /**
   * Initializes a new instance of <code>Socket</code> object without
   * connecting to a remote host.  This is useful for subclasses of socket
   * that might want this behavior.
   * <p>
   * Additionally, this socket will be created using the supplied
   * implementation class instead the default class or one returned by a
   * factory.  If this value is <code>null</code>, the default Socket
   * implementation is used.
   *
   * @param impl The <code>SocketImpl</code> to use for this
   *             <code>Socket</code>
   *
   * @exception SocketException If an error occurs
   *
   * @since 1.1
   */
  protected Socket(SocketImpl impl) throws SocketException
  {
    if (impl == null)
      this.impl = new PlainSocketImpl();
    else
      this.impl = impl;
  }

  /**
   * Initializes a new instance of <code>Socket</code> and connects to the
   * hostname and port specified as arguments.
   *
   * @param host The name of the host to connect to
   * @param port The port number to connect to
   *
   * @exception UnknownHostException If the hostname cannot be resolved to a
   * network address.
   * @exception IOException If an error occurs
   * @exception SecurityException If a security manager exists and its
   * checkConnect method doesn't allow the operation
   */
  public Socket(String host, int port)
    throws UnknownHostException, IOException
  {
    this(InetAddress.getByName(host), port, null, 0, true);
  }

  /**
   * Initializes a new instance of <code>Socket</code> and connects to the
   * address and port number specified as arguments.
   *
   * @param address The address to connect to
   * @param port The port number to connect to
   *
   * @exception IOException If an error occurs
   * @exception SecurityException If a security manager exists and its
   * checkConnect method doesn't allow the operation
   */
  public Socket(InetAddress address, int port) throws IOException
  {
    this(address, port, null, 0, true);
  }

  /**
   * Initializes a new instance of <code>Socket</code> that connects to the
   * named host on the specified port and binds to the specified local address
   * and port.
   *
   * @param host The name of the remote host to connect to.
   * @param port The remote port to connect to.
   * @param localAddr The local address to bind to.
   * @param localPort The local port to bind to.
   *
   * @exception SecurityException If the <code>SecurityManager</code>
   * exists and does not allow a connection to the specified host/port or
   * binding to the specified local host/port.
   * @exception IOException If a connection error occurs.
   *
   * @since 1.1
   */
  public Socket(String host, int port, InetAddress localAddr, int localPort)
    throws IOException
  {
    this(InetAddress.getByName(host), port, localAddr, localPort, true);
  }

  /**
   * Initializes a new instance of <code>Socket</code> and connects to the
   * address and port number specified as arguments, plus binds to the
   * specified local address and port.
   *
   * @param address The remote address to connect to
   * @param port The remote port to connect to
   * @param localAddr The local address to connect to
   * @param localPort The local port to connect to
   *
   * @exception IOException If an error occurs
   * @exception SecurityException If a security manager exists and its
   * checkConnect method doesn't allow the operation
   *
   * @since 1.1
   */
  public Socket(InetAddress address, int port, InetAddress localAddr,
                int localPort) throws IOException
  {
    this(address, port, localAddr, localPort, true);
  }

  /**
   * Initializes a new instance of <code>Socket</code> and connects to the
   * hostname and port specified as arguments.  If the stream argument is set
   * to <code>true</code>, then a stream socket is created.  If it is
   * <code>false</code>, a datagram socket is created.
   *
   * @param host The name of the host to connect to
   * @param port The port to connect to
   * @param stream <code>true</code> for a stream socket, <code>false</code>
   * for a datagram socket
   *
   * @exception IOException If an error occurs
   * @exception SecurityException If a security manager exists and its
   * checkConnect method doesn't allow the operation
   *
   * @deprecated Use the <code>DatagramSocket</code> class to create
   * datagram oriented sockets.
   */
  public Socket(String host, int port, boolean stream)
    throws IOException
  {
    this(InetAddress.getByName(host), port, null, 0, stream);
  }

  /**
   * Initializes a new instance of <code>Socket</code> and connects to the
   * address and port number specified as arguments.  If the stream param is
   * <code>true</code>, a stream socket will be created, otherwise a datagram
   * socket is created.
   *
   * @param host The address to connect to
   * @param port The port number to connect to
   * @param stream <code>true</code> to create a stream socket,
   * <code>false</code> to create a datagram socket.
   *
   * @exception IOException If an error occurs
   * @exception SecurityException If a security manager exists and its
   * checkConnect method doesn't allow the operation
   *
   * @deprecated Use the <code>DatagramSocket</code> class to create
   * datagram oriented sockets.
   */
  public Socket(InetAddress host, int port, boolean stream)
    throws IOException
  {
    this(host, port, null, 0, stream);
  }

  /**
   * This constructor is where the real work takes place.  Connect to the
   * specified address and port.  Use default local values if not specified,
   * otherwise use the local host and port passed in.  Create as stream or
   * datagram based on "stream" argument.
   * <p>
   *
   * @param raddr The remote address to connect to
   * @param rport The remote port to connect to
   * @param laddr The local address to connect to
   * @param lport The local port to connect to
   * @param stream true for a stream socket, false for a datagram socket
   *
   * @exception IOException If an error occurs
   * @exception SecurityException If a security manager exists and its
   * checkConnect method doesn't allow the operation
   */
  private Socket(InetAddress raddr, int rport, InetAddress laddr, int lport,
                 boolean stream) throws IOException
  {
    this();

    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      sm.checkConnect(raddr.getHostAddress(), rport);

    // bind socket
    SocketAddress bindaddr =
      laddr == null ? null : new InetSocketAddress(laddr, lport);
    bind(bindaddr);

    // Connect socket in case of Exceptions we must close the socket
    // because an exception in the constructor means that the caller will
    // not have a reference to this instance.
    // Note: You may have the idea that the exception treatment
    // should be moved into connect() but there is a Mauve test which
    // shows that a failed connect should not close the socket.
    try
      {
        connect(new InetSocketAddress(raddr, rport));
      }
    catch (IOException ioe)
      {
        impl.close();
        throw ioe;
      }
    catch (RuntimeException re)
      {
        impl.close();
        throw re;
      }

    // FIXME: JCL p. 1586 says if localPort is unspecified, bind to any port,
    // i.e. '0' and if localAddr is unspecified, use getLocalAddress() as
    // that default.  JDK 1.2 doc infers not to do a bind.
  }

  private SocketImpl getImpl() throws SocketException
  {
    if (! implCreated)
      {
        try
          {
            impl.create(true);
          }
        catch (IOException x)
          {
            throw (SocketException) new SocketException().initCause(x);
          }
        implCreated = true;
      }
    return impl;
  }

  /**
   * Binds the socket to the given local address/port
   *
   * @param bindpoint The address/port to bind to
   *
   * @exception IOException If an error occurs
   * @exception SecurityException If a security manager exists and its
   * checkConnect method doesn't allow the operation
   * @exception IllegalArgumentException If the address type is not supported
   *
   * @since 1.4
   */
  public void bind(SocketAddress bindpoint) throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    // XXX: JDK 1.4.1 API documentation says that if bindpoint is null the
    // socket will be bound to an ephemeral port and a valid local address.
    if (bindpoint == null)
      bindpoint = new InetSocketAddress(InetAddress.ANY_IF, 0);

    if (! (bindpoint instanceof InetSocketAddress))
      throw new IllegalArgumentException();

    InetSocketAddress tmp = (InetSocketAddress) bindpoint;

    // bind to address/port
    try
      {
        getImpl().bind(tmp.getAddress(), tmp.getPort());
        bound = true;
      }
    catch (IOException exception)
      {
        close();
        throw exception;
      }
    catch (RuntimeException exception)
      {
        close();
        throw exception;
      }
    catch (Error error)
      {
        close();
        throw error;
      }
  }

  /**
   * Connects the socket with a remote address.
   *
   * @param endpoint The address to connect to
   *
   * @exception IOException If an error occurs
   * @exception IllegalArgumentException If the addess type is not supported
   * @exception IllegalBlockingModeException If this socket has an associated
   * channel, and the channel is in non-blocking mode
   *
   * @since 1.4
   */
  public void connect(SocketAddress endpoint) throws IOException
  {
    connect(endpoint, 0);
  }

  /**
   * Connects the socket with a remote address. A timeout of zero is
   * interpreted as an infinite timeout. The connection will then block
   * until established or an error occurs.
   *
   * @param endpoint The address to connect to
   * @param timeout The length of the timeout in milliseconds, or
   * 0 to indicate no timeout.
   *
   * @exception IOException If an error occurs
   * @exception IllegalArgumentException If the address type is not supported
   * @exception IllegalBlockingModeException If this socket has an associated
   * channel, and the channel is in non-blocking mode
   * @exception SocketTimeoutException If the timeout is reached
   *
   * @since 1.4
   */
  public void connect(SocketAddress endpoint, int timeout)
    throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    if (! (endpoint instanceof InetSocketAddress))
      throw new IllegalArgumentException("unsupported address type");

    // The Sun spec says that if we have an associated channel and
    // it is in non-blocking mode, we throw an IllegalBlockingModeException.
    // However, in our implementation if the channel itself initiated this
    // operation, then we must honor it regardless of its blocking mode.
    if (getChannel() != null && ! getChannel().isBlocking()
        && ! ((PlainSocketImpl) getImpl()).isInChannelOperation())
      throw new IllegalBlockingModeException();

    if (! isBound())
      bind(null);

    getImpl().connect(endpoint, timeout);
  }

  /**
   * Returns the address of the remote end of the socket.  If this socket
   * is not connected, then <code>null</code> is returned.
   *
   * @return The remote address this socket is connected to
   */
  public InetAddress getInetAddress()
  {
    if (! isConnected())
      return null;

    try
      {
        return getImpl().getInetAddress();
      }
    catch (SocketException e)
      {
        // This cannot happen as we are connected.
      }

    return null;
  }

  /**
   * Returns the local address to which this socket is bound.  If this socket
   * is not connected, then a wildcard address, for which
   * @see InetAddress#isAnyLocalAddress() is <code>true</code>, is returned.
   *
   * @return The local address
   *
   * @since 1.1
   */
  public InetAddress getLocalAddress()
  {
    if (! isBound())
      return InetAddress.ANY_IF;

    InetAddress addr = null;

    if (impl instanceof PlainSocketImpl)
      addr = ((PlainSocketImpl) impl).getLocalAddress().getAddress();

    if (addr == null)
      {
        try
          {
            addr = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
          }
        catch (SocketException e)
          {
            // (hopefully) shouldn't happen
            // throw new java.lang.InternalError
            //      ("Error in PlainSocketImpl.getOption");
            return null;
          }
      }

    // FIXME: According to libgcj, checkConnect() is supposed to be called
    // before performing this operation.  Problems: 1) We don't have the
    // addr until after we do it, so we do a post check.  2). The docs I
    // see don't require this in the Socket case, only DatagramSocket, but
    // we'll assume they mean both.
    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      sm.checkConnect(addr.getHostName(), getLocalPort());

    return addr;
  }

  /**
   * Returns the port number of the remote end of the socket connection.  If
   * this socket is not connected, then 0 is returned.
   *
   * @return The remote port this socket is connected to
   */
  public int getPort()
  {
    if (! isConnected())
      return 0;

    try
      {
        return getImpl().getPort();
      }
    catch (SocketException e)
      {
        // This cannot happen as we are connected.
      }

    return 0;
  }

  /**
   * Returns the local port number to which this socket is bound.  If this
   * socket is not connected, then -1 is returned.
   *
   * @return The local port
   */
  public int getLocalPort()
  {
    if (! isBound())
      return -1;

    try
      {
        if (getImpl() != null)
          return getImpl().getLocalPort();
      }
    catch (SocketException e)
      {
        // This cannot happen as we are bound.
      }

    return -1;
  }

  /**
   * Returns local socket address.
   *
   * @return the local socket address, null if not bound
   *
   * @since 1.4
   */
  public SocketAddress getLocalSocketAddress()
  {
    if (! isBound())
      return null;

    InetAddress addr = getLocalAddress();

    try
      {
        return new InetSocketAddress(addr, getImpl().getLocalPort());
      }
    catch (SocketException e)
      {
        // This cannot happen as we are bound.
        return null;
      }
  }

  /**
   * Returns the remote socket address.
   *
   * @return the remote socket address, null of not connected
   *
   * @since 1.4
   */
  public SocketAddress getRemoteSocketAddress()
  {
    if (! isConnected())
      return null;

    try
      {
        return new InetSocketAddress(getImpl().getInetAddress(),
                                     getImpl().getPort());
      }
    catch (SocketException e)
      {
        // This cannot happen as we are connected.
        return null;
      }
  }

  /**
   * Returns an InputStream for reading from this socket.
   *
   * @return The InputStream object
   *
   * @exception IOException If an error occurs or Socket is not connected
   */
  public InputStream getInputStream() throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    if (! isConnected())
      throw new IOException("not connected");

    return getImpl().getInputStream();
  }

  /**
   * Returns an OutputStream for writing to this socket.
   *
   * @return The OutputStream object
   *
   * @exception IOException If an error occurs or Socket is not connected
   */
  public OutputStream getOutputStream() throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    if (! isConnected())
      throw new IOException("not connected");

    return getImpl().getOutputStream();
  }

  /**
   * Sets the TCP_NODELAY option on the socket.
   *
   * @param on true to enable, false to disable
   *
   * @exception SocketException If an error occurs or Socket is not connected
   *
   * @since 1.1
   */
  public void setTcpNoDelay(boolean on) throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
  }

  /**
   * Tests whether or not the TCP_NODELAY option is set on the socket.
   * Returns true if enabled, false if disabled. When on it disables the
   * Nagle algorithm which means that packets are always send immediatly and
   * never merged together to reduce network trafic.
   *
   * @return Whether or not TCP_NODELAY is set
   *
   * @exception SocketException If an error occurs or Socket not connected
   *
   * @since 1.1
   */
  public boolean getTcpNoDelay() throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    Object on = getImpl().getOption(SocketOptions.TCP_NODELAY);

    if (on instanceof Boolean)
      return (((Boolean) on).booleanValue());
    else
      throw new SocketException("Internal Error");
  }

  /**
   * Sets the value of the SO_LINGER option on the socket.  If the
   * SO_LINGER option is set on a socket and there is still data waiting to
   * be sent when the socket is closed, then the close operation will block
   * until either that data is delivered or until the timeout period
   * expires.  The linger interval is specified in hundreths of a second
   * (platform specific?)
   *
   * @param on true to enable SO_LINGER, false to disable
   * @param linger The SO_LINGER timeout in hundreths of a second or -1 if
   * SO_LINGER not set.
   *
   * @exception SocketException If an error occurs or Socket not connected
   * @exception IllegalArgumentException If linger is negative
   *
   * @since 1.1
   */
  public void setSoLinger(boolean on, int linger) throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    if (on)
      {
        if (linger < 0)
          throw new IllegalArgumentException("SO_LINGER must be >= 0");

        if (linger > 65535)
          linger = 65535;

        getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(linger));
      }
    else
      getImpl().setOption(SocketOptions.SO_LINGER, Integer.valueOf(-1));
  }

  /**
   * Returns the value of the SO_LINGER option on the socket.  If the
   * SO_LINGER option is set on a socket and there is still data waiting to
   * be sent when the socket is closed, then the close operation will block
   * until either that data is delivered or until the timeout period
   * expires.  This method either returns the timeouts (in hundredths of
   * of a second (platform specific?)) if SO_LINGER is set, or -1 if
   * SO_LINGER is not set.
   *
   * @return The SO_LINGER timeout in hundreths of a second or -1
   * if SO_LINGER not set
   *
   * @exception SocketException If an error occurs or Socket is not connected
   *
   * @since 1.1
   */
  public int getSoLinger() throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    Object linger = getImpl().getOption(SocketOptions.SO_LINGER);

    if (linger instanceof Integer)
      return (((Integer) linger).intValue());
    else
      return -1;
  }

  /**
   * Sends urgent data through the socket
   *
   * @param data The data to send.
   * Only the lowest eight bits of data are sent
   *
   * @exception IOException If an error occurs
   *
   * @since 1.4
   */
  public void sendUrgentData(int data) throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    getImpl().sendUrgentData(data);
  }

  /**
   * Enables/disables the SO_OOBINLINE option
   *
   * @param on True if SO_OOBLINE should be enabled
   *
   * @exception SocketException If an error occurs
   *
   * @since 1.4
   */
  public void setOOBInline(boolean on) throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    getImpl().setOption(SocketOptions.SO_OOBINLINE, Boolean.valueOf(on));
  }

  /**
   * Returns the current setting of the SO_OOBINLINE option for this socket
   *
   * @return True if SO_OOBINLINE is set, false otherwise.
   *
   * @exception SocketException If an error occurs
   *
   * @since 1.4
   */
  public boolean getOOBInline() throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    Object buf = getImpl().getOption(SocketOptions.SO_OOBINLINE);

    if (buf instanceof Boolean)
      return (((Boolean) buf).booleanValue());
    else
      throw new SocketException("Internal Error: Unexpected type");
  }

  /**
   * Sets the value of the SO_TIMEOUT option on the socket.  If this value
   * is set, and an read/write is performed that does not complete within
   * the timeout period, a short count is returned (or an EWOULDBLOCK signal
   * would be sent in Unix if no data had been read).  A value of 0 for
   * this option implies that there is no timeout (ie, operations will
   * block forever).  On systems that have separate read and write timeout
   * values, this method returns the read timeout.  This
   * value is in milliseconds.
   *
   * @param timeout The length of the timeout in milliseconds, or
   * 0 to indicate no timeout.
   *
   * @exception SocketException If an error occurs or Socket not connected
   *
   * @since 1.1
   */
  public synchronized void setSoTimeout(int timeout) throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    if (timeout < 0)
      throw new IllegalArgumentException("SO_TIMEOUT value must be >= 0");

    getImpl().setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
  }

  /**
   * Returns the value of the SO_TIMEOUT option on the socket.  If this value
   * is set, and an read/write is performed that does not complete within
   * the timeout period, a short count is returned (or an EWOULDBLOCK signal
   * would be sent in Unix if no data had been read).  A value of 0 for
   * this option implies that there is no timeout (ie, operations will
   * block forever).  On systems that have separate read and write timeout
   * values, this method returns the read timeout.  This
   * value is in thousandths of a second (implementation specific?).
   *
   * @return The length of the timeout in thousandth's of a second or 0
   * if not set
   *
   * @exception SocketException If an error occurs or Socket not connected
   *
   * @since 1.1
   */
  public synchronized int getSoTimeout() throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    Object timeout = getImpl().getOption(SocketOptions.SO_TIMEOUT);
    if (timeout instanceof Integer)
      return (((Integer) timeout).intValue());
    else
      return 0;
  }

  /**
   * This method sets the value for the system level socket option
   * SO_SNDBUF to the specified value.  Note that valid values for this
   * option are specific to a given operating system.
   *
   * @param size The new send buffer size.
   *
   * @exception SocketException If an error occurs or Socket not connected
   * @exception IllegalArgumentException If size is 0 or negative
   *
   * @since 1.2
   */
  public void setSendBufferSize(int size) throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    if (size <= 0)
      throw new IllegalArgumentException("SO_SNDBUF value must be > 0");

    getImpl().setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
  }

  /**
   * This method returns the value of the system level socket option
   * SO_SNDBUF, which is used by the operating system to tune buffer
   * sizes for data transfers.
   *
   * @return The send buffer size.
   *
   * @exception SocketException If an error occurs or socket not connected
   *
   * @since 1.2
   */
  public int getSendBufferSize() throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    Object buf = getImpl().getOption(SocketOptions.SO_SNDBUF);

    if (buf instanceof Integer)
      return (((Integer) buf).intValue());
    else
      throw new SocketException("Internal Error: Unexpected type");
  }

  /**
   * This method sets the value for the system level socket option
   * SO_RCVBUF to the specified value.  Note that valid values for this
   * option are specific to a given operating system.
   *
   * @param size The new receive buffer size.
   *
   * @exception SocketException If an error occurs or Socket is not connected
   * @exception IllegalArgumentException If size is 0 or negative
   *
   * @since 1.2
   */
  public void setReceiveBufferSize(int size) throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    if (size <= 0)
      throw new IllegalArgumentException("SO_RCVBUF value must be > 0");

    getImpl().setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
  }

  /**
   * This method returns the value of the system level socket option
   * SO_RCVBUF, which is used by the operating system to tune buffer
   * sizes for data transfers.
   *
   * @return The receive buffer size.
   *
   * @exception SocketException If an error occurs or Socket is not connected
   *
   * @since 1.2
   */
  public int getReceiveBufferSize() throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    Object buf = getImpl().getOption(SocketOptions.SO_RCVBUF);

    if (buf instanceof Integer)
      return (((Integer) buf).intValue());
    else
      throw new SocketException("Internal Error: Unexpected type");
  }

  /**
   * This method sets the value for the socket level socket option
   * SO_KEEPALIVE.
   *
   * @param on True if SO_KEEPALIVE should be enabled
   *
   * @exception SocketException If an error occurs or Socket is not connected
   *
   * @since 1.3
   */
  public void setKeepAlive(boolean on) throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    getImpl().setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(on));
  }

  /**
   * This method returns the value of the socket level socket option
   * SO_KEEPALIVE.
   *
   * @return The setting
   *
   * @exception SocketException If an error occurs or Socket is not connected
   *
   * @since 1.3
   */
  public boolean getKeepAlive() throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    Object buf = getImpl().getOption(SocketOptions.SO_KEEPALIVE);

    if (buf instanceof Boolean)
      return (((Boolean) buf).booleanValue());
    else
      throw new SocketException("Internal Error: Unexpected type");
  }

  /**
   * Closes the socket.
   *
   * @exception IOException If an error occurs
   */
  public synchronized void close() throws IOException
  {
    if (isClosed())
      return;

    impl.close();
    impl = null;
  }

  /**
   * Converts this <code>Socket</code> to a <code>String</code>.
   *
   * @return The <code>String</code> representation of this <code>Socket</code>
   */
  public String toString()
  {
    try
      {
        if (isConnected())
          return (super.toString()
                  + " [addr=" + getImpl().getInetAddress() + ",port="
                  + getImpl().getPort() + ",localport="
                  + getImpl().getLocalPort() + "]");
      }
    catch (SocketException e)
      {
        // This cannot happen as we are connected.
      }

    return super.toString() + " [unconnected]";
  }

  /**
   * Sets the <code>SocketImplFactory</code>.  This may be done only once per
   * virtual machine.  Subsequent attempts will generate a
   * <code>SocketException</code>.  Note that a <code>SecurityManager</code>
   * check is made prior to setting the factory.  If
   * insufficient privileges exist to set the factory, then an
   * <code>IOException</code> will be thrown.
   *
   * @param fac the factory to set
   *
   * @exception SecurityException If the <code>SecurityManager</code> does
   * not allow this operation.
   * @exception SocketException If the SocketImplFactory is already defined
   * @exception IOException If any other error occurs
   */
  public static synchronized void setSocketImplFactory(SocketImplFactory fac)
    throws IOException
  {
    // See if already set
    if (factory != null)
      throw new SocketException("SocketImplFactory already defined");

    // Check permissions
    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      sm.checkSetFactory();

    if (fac == null)
      throw new SocketException("SocketImplFactory cannot be null");

    factory = fac;
  }

  /**
   * Closes the input side of the socket stream.
   *
   * @exception IOException If an error occurs.
   *
   * @since 1.3
   */
  public void shutdownInput() throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    getImpl().shutdownInput();
    inputShutdown = true;
  }

  /**
   * Closes the output side of the socket stream.
   *
   * @exception IOException If an error occurs.
   *
   * @since 1.3
   */
  public void shutdownOutput() throws IOException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    getImpl().shutdownOutput();
    outputShutdown = true;
  }

  /**
   * Returns the socket channel associated with this socket.
   *
   * @return the associated socket channel,
   * null if no associated channel exists
   *
   * @since 1.4
   */
  public SocketChannel getChannel()
  {
    return null;
  }

  /**
   * Checks if the SO_REUSEADDR option is enabled
   *
   * @return True if SO_REUSEADDR is set, false otherwise.
   *
   * @exception SocketException If an error occurs
   *
   * @since 1.4
   */
  public boolean getReuseAddress() throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    Object reuseaddr = getImpl().getOption(SocketOptions.SO_REUSEADDR);

    if (! (reuseaddr instanceof Boolean))
      throw new SocketException("Internal Error");

    return ((Boolean) reuseaddr).booleanValue();
  }

  /**
   * Enables/Disables the SO_REUSEADDR option
   *
   * @param reuseAddress true if SO_REUSEADDR should be enabled,
   * false otherwise
   *
   * @exception SocketException If an error occurs
   *
   * @since 1.4
   */
  public void setReuseAddress(boolean reuseAddress) throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    getImpl().setOption(SocketOptions.SO_REUSEADDR,
                        Boolean.valueOf(reuseAddress));
  }

  /**
   * Returns the current traffic class
   *
   * @return The current traffic class.
   *
   * @exception SocketException If an error occurs
   *
   * @see Socket#setTrafficClass(int tc)
   *
   * @since 1.4
   */
  public int getTrafficClass() throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    Object obj = getImpl().getOption(SocketOptions.IP_TOS);

    if (obj instanceof Integer)
      return ((Integer) obj).intValue();
    else
      throw new SocketException("Unexpected type");
  }

  /**
   * Sets the traffic class value
   *
   * @param tc The traffic class
   *
   * @exception SocketException If an error occurs
   * @exception IllegalArgumentException If tc value is illegal
   *
   * @see Socket#getTrafficClass()
   *
   * @since 1.4
   */
  public void setTrafficClass(int tc) throws SocketException
  {
    if (isClosed())
      throw new SocketException("socket is closed");

    if (tc < 0 || tc > 255)
      throw new IllegalArgumentException();

    getImpl().setOption(SocketOptions.IP_TOS, Integer.valueOf(tc));
  }

  /**
   * Checks if the socket is connected
   *
   * @return True if socket is connected, false otherwise.
   *
   * @since 1.4
   */
  public boolean isConnected()
  {
    if (impl == null)
      return false;

    return impl.getInetAddress() != null;
  }

  /**
   * Checks if the socket is already bound.
   *
   * @return True if socket is bound, false otherwise.
   *
   * @since 1.4
   */
  public boolean isBound()
  {
    if (isClosed())
      return false;
    if (impl instanceof PlainSocketImpl)
      {
        InetSocketAddress addr = ((PlainSocketImpl) impl).getLocalAddress();
        return addr != null && addr.getAddress() != null;
      }
    return bound;
  }

  /**
   * Checks if the socket is closed.
   *
   * @return True if socket is closed, false otherwise.
   *
   * @since 1.4
   */
  public boolean isClosed()
  {
    SocketChannel channel = getChannel();

    return impl == null || (channel != null && ! channel.isOpen());
  }

  /**
   * Checks if the socket's input stream is shutdown
   *
   * @return True if input is shut down.
   *
   * @since 1.4
   */
  public boolean isInputShutdown()
  {
    return inputShutdown;
  }

  /**
   * Checks if the socket's output stream is shutdown
   *
   * @return True if output is shut down.
   *
   * @since 1.4
   */
  public boolean isOutputShutdown()
  {
    return outputShutdown;
  }
}
