/**
  * Creates a new socket that is not bound to any local address/port and is not connected to any
  * remote address/port. The stream parameter will be ignored since PlainSocketImpl always is a
  * stream socket. Datagram sockets are handled by PlainDatagramSocketImpl.
  *
  * @param stream <code>true</code> for stream sockets, <code>false</code> for datagram sockets
  */
 protected synchronized void create(boolean stream) throws IOException {
   channel = new SocketChannelImpl(false);
   VMChannel vmchannel = channel.getVMChannel();
   vmchannel.initSocket(stream);
   channel.configureBlocking(true);
   impl.getState().setChannelFD(vmchannel.getState());
 }
  /**
   * Returns the current setting of the specified option. The Object returned will be an Integer for
   * options that have integer values. The option_id is one of the defined constants in this
   * interface.
   *
   * @param optionId the option identifier
   * @return the current value of the option
   * @throws SocketException if an error occurs
   */
  public Object getOption(int optionId) throws SocketException {
    if (optionId == SO_BINDADDR) {
      try {
        return channel.getVMChannel().getLocalAddress().getAddress();
      } catch (IOException ioe) {
        SocketException se = new SocketException();
        se.initCause(ioe);
        throw se;
      }
    }

    // This filters options which are invalid for TCP.
    switch (optionId) {
      case SO_LINGER:
      case IP_MULTICAST_LOOP:
      case SO_BROADCAST:
      case SO_KEEPALIVE:
      case SO_OOBINLINE:
      case TCP_NODELAY:
      case IP_TOS:
      case SO_RCVBUF:
      case SO_SNDBUF:
      case SO_TIMEOUT:
      case SO_REUSEADDR:
        return impl.getOption(optionId);
      default:
        throw new SocketException("Unrecognized TCP option: " + optionId);
    }
  }
 public InetSocketAddress getLocalAddress() {
   if (channel == null) return null;
   try {
     return channel.getVMChannel().getLocalAddress();
   } catch (IOException ioe) {
     return null;
   }
 }
 /* (non-Javadoc)
  * @see java.net.SocketImpl#getLocalPort()
  */
 protected int getLocalPort() {
   if (channel == null) return -1;
   try {
     InetSocketAddress local = channel.getVMChannel().getLocalAddress();
     if (local == null) return -1;
     return local.getPort();
   } catch (IOException ioe) {
     return -1;
   }
 }
  /* (non-Javadoc)
   * @see java.net.SocketImpl#getPort()
   */
  protected int getPort() {
    if (channel == null) return -1;

    try {
      InetSocketAddress remote = channel.getVMChannel().getPeerAddress();
      if (remote == null) return -1;
      return remote.getPort();
    } catch (IOException ioe) {
      return -1;
    }
  }
 /**
  * Accepts a new connection on this socket and returns in in the passed in SocketImpl.
  *
  * @param impl The SocketImpl object to accept this connection.
  */
 protected synchronized void accept(SocketImpl impl) throws IOException {
   if (channel == null) create(true);
   if (!(impl instanceof PlainSocketImpl))
     throw new IOException("incompatible SocketImpl: " + impl.getClass().getName());
   PlainSocketImpl that = (PlainSocketImpl) impl;
   VMChannel c = channel.getVMChannel().accept();
   that.impl.getState().setChannelFD(c.getState());
   that.channel = new SocketChannelImpl(c);
   that.setOption(SO_REUSEADDR, Boolean.TRUE);
   // Reset the inherited timeout.
   that.setOption(SO_TIMEOUT, Integer.valueOf(0));
 }
  /* (non-Javadoc)
   * @see java.net.SocketImpl#getInetAddress()
   */
  protected InetAddress getInetAddress() {
    if (channel == null) return null;

    try {
      InetSocketAddress remote = channel.getVMChannel().getPeerAddress();
      if (remote == null) return null;
      // To mimic behavior of the RI the InetAddress instance which was
      // used to establish the connection is returned instead of one that
      // was created by the native layer (this preserves exact hostnames).
      if (address != null) return address;

      return remote.getAddress();
    } catch (IOException ioe) {
      return null;
    }
  }
 public VMChannel getVMChannel() {
   if (channel == null) return null;
   return channel.getVMChannel();
 }
 /**
  * Returns the number of bytes that the caller can read from this socket without blocking.
  *
  * @return the number of readable bytes before blocking
  * @throws IOException if an error occurs
  */
 protected int available() throws IOException {
   if (channel == null) throw new SocketException("not connected");
   return channel.getVMChannel().available();
 }
 /**
  * Binds to the specified port on the specified addr. Note that this addr must represent a local
  * IP address. **** How bind to INADDR_ANY? ****
  *
  * @param addr the address to bind to
  * @param port the port number to bind to
  * @throws IOException if an error occurs
  */
 protected synchronized void bind(InetAddress addr, int port) throws IOException {
   if (channel == null) create(true);
   impl.bind(new InetSocketAddress(addr, port));
   localport = channel.getVMChannel().getLocalAddress().getPort();
 }