/* VMPlainSocketImpl.java -- VM interface for default socket implementation
   Copyright (C) 2005, 2006 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 gnu.java.net;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.SocketOptions;

import gnu.classpath.Configuration;
import gnu.java.nio.VMChannel;

/**
 * The VM interface for {@link gnu.java.net.PlainSocketImpl}.
 *
 * @author Ingo Proetel (proetel@aicas.com)
 * @author Roman Kennke (kennke@aicas.com)
 */
public final class VMPlainSocketImpl
{
  /** Option id for time to live
   */
  private static final int CP_IP_TTL = 0x1E61;

  private final State nfd;

  /**
   * Static initializer to load native library.
   */
  static
  {
    if (Configuration.INIT_LOAD_LIBRARY)
      {
        System.loadLibrary("javanet");
      }
  }

  public VMPlainSocketImpl()
  {
    // XXX consider adding security check here.
    nfd = new State();
  }

  public VMPlainSocketImpl(VMChannel channel) throws IOException
  {
    this();
    nfd.setChannelFD(channel.getState());
  }

  public State getState()
  {
    return nfd;
  }

  /** This method exists to hide the CP_IP_TTL value from
   * higher levels.
   *
   * Always think of JNode ... :)
   */
  public void setTimeToLive(int ttl)
    throws SocketException
  {
    try
      {
        setOption(nfd.getNativeFD(), CP_IP_TTL, ttl);
      }
    catch (IOException ioe)
      {
        SocketException se = new SocketException();
        se.initCause(ioe);
        throw se;
      }
  }

  public int getTimeToLive()
    throws SocketException
  {
    try
      {
        return getOption(nfd.getNativeFD(), CP_IP_TTL);
      }
    catch (IOException ioe)
      {
        SocketException se = new SocketException();
        se.initCause(ioe);
        throw se;
      }
  }

  public void setOption(int optionId, Object optionValue)
    throws SocketException
  {
    int value;
    if (optionValue instanceof Integer)
      value = ((Integer) optionValue).intValue();
    else if (optionValue instanceof Boolean)
      // Switching off the linger behavior is done by setting
      // the value to -1. This is how the Java API interprets
      // it.
      value = ((Boolean) optionValue).booleanValue()
              ? 1
              : (optionId == SocketOptions.SO_LINGER)
              ? -1
              : 0;
    else
      throw new IllegalArgumentException("option value type "
                                         + optionValue.getClass().getName());

    try
      {
        setOption(nfd.getNativeFD(), optionId, value);
      }
    catch (IOException ioe)
      {
        SocketException se = new SocketException();
        se.initCause(ioe);
        throw se;
      }
  }

  private static native void setOption(int fd, int id, int value)
    throws SocketException;

  public void setMulticastInterface(int optionId, InetAddress addr)
    throws SocketException
  {
    try
      {
        if (addr instanceof Inet4Address)
          setMulticastInterface(nfd.getNativeFD(), optionId, (Inet4Address) addr);
        else if (addr instanceof Inet6Address)
          {
            NetworkInterface iface = NetworkInterface.getByInetAddress(addr);
            setMulticastInterface6(nfd.getNativeFD(), optionId, iface.getName());
          }
        else
          throw new SocketException("Unknown address format: " + addr);
      }
    catch (SocketException se)
      {
        throw se;
      }
    catch (IOException ioe)
      {
        SocketException se = new SocketException();
        se.initCause(ioe);
        throw se;
      }
  }

  private static native void setMulticastInterface(int fd,
                                                   int optionId,
                                                   Inet4Address addr);

  private static native void setMulticastInterface6(int fd,
                                                    int optionId,
                                                    String ifName);

  /**
   * Get a socket option. This implementation is only required to support
   * socket options that are boolean values, which include:
   *
   *  SocketOptions.IP_MULTICAST_LOOP
   *  SocketOptions.SO_BROADCAST
   *  SocketOptions.SO_KEEPALIVE
   *  SocketOptions.SO_OOBINLINE
   *  SocketOptions.SO_REUSEADDR
   *  SocketOptions.TCP_NODELAY
   *
   * and socket options that are integer values, which include:
   *
   *  SocketOptions.IP_TOS
   *  SocketOptions.SO_LINGER
   *  SocketOptions.SO_RCVBUF
   *  SocketOptions.SO_SNDBUF
   *  SocketOptions.SO_TIMEOUT
   *
   * @param optionId The option ID to fetch.
   * @return A {@link Boolean} or {@link Integer} containing the socket
   *  option.
   * @throws SocketException
   */
  public Object getOption(int optionId) throws SocketException
  {
    int value;
    try
      {
        value = getOption(nfd.getNativeFD(), optionId);
      }
    catch (IOException ioe)
      {
        SocketException se = new SocketException();
        se.initCause(ioe);
        throw se;
      }

    switch (optionId)
      {
        case SocketOptions.IP_MULTICAST_LOOP:
        case SocketOptions.SO_BROADCAST:
        case SocketOptions.SO_KEEPALIVE:
        case SocketOptions.SO_OOBINLINE:
        case SocketOptions.SO_REUSEADDR:
        case SocketOptions.TCP_NODELAY:
          return Boolean.valueOf(value != 0);

        case SocketOptions.IP_TOS:
        case SocketOptions.SO_LINGER:
        case SocketOptions.SO_RCVBUF:
        case SocketOptions.SO_SNDBUF:
        case SocketOptions.SO_TIMEOUT:
          return new Integer(value);

        default:
          throw new SocketException("getting option " + optionId +
                                    " not supported here");
      }
  }

  private static native int getOption(int fd, int id) throws SocketException;

  /**
   * Returns an Inet4Address or Inet6Address instance belonging to the
   * interface which is set as the multicast interface.
   *
   * The optionId is provided to make it possible that the native
   * implementation may do something different depending on whether
   * the value is SocketOptions.IP_MULTICAST_IF or
   * SocketOptions.IP_MULTICAST_IF2.
   */
  public InetAddress getMulticastInterface(int optionId)
    throws SocketException
  {
    try
      {
        return getMulticastInterface(nfd.getNativeFD(), optionId);
      }
    catch (IOException ioe)
      {
        SocketException se = new SocketException();
        se.initCause(ioe);
        throw se;
      }
  }

  private static native InetAddress getMulticastInterface(int fd,
                                                          int optionId);

  /**
   * Binds this socket to the given local address and port.
   *
   * @param address The address to bind to; the InetAddress is either
   *  an IPv4 or IPv6 address.
   * @throws IOException If binding fails; for example, if the port
   *  in the given InetSocketAddress is privileged, and the current
   *  process has insufficient privileges.
   */
  public void bind(InetSocketAddress address) throws IOException
  {
    InetAddress addr = address.getAddress();
    if (addr instanceof Inet4Address)
      {
        bind (nfd.getNativeFD(), addr.getAddress(), address.getPort());
      }
    else if (addr instanceof Inet6Address)
      bind6 (nfd.getNativeFD(), addr.getAddress(), address.getPort());
    else
      throw new SocketException ("unsupported address type");
  }

  /**
   * Native bind function for IPv4 addresses. The addr array must be
   * exactly four bytes long.
   *
   * VMs without native support need not implement this.
   *
   * @param fd The native file descriptor integer.
   * @param addr The IPv4 address, in network byte order.
   * @param port The port to bind to.
   * @throws IOException
   */
  private static native void bind(int fd, byte[] addr, int port)
    throws IOException;

  /**
   * Native bind function for IPv6 addresses. The addr array must be
   * exactly sixteen bytes long.
   *
   * VMs without native support need not implement this.
   *
   * @param fd The native file descriptor integer.
   * @param addr The IPv6 address, in network byte order.
   * @param port The port to bind to.
   * @throws IOException
   */
  private static native void bind6(int fd, byte[] addr, int port)
    throws IOException;

  /**
   * Listen on this socket for incoming connections.
   *
   * @param backlog The backlog of connections.
   * @throws IOException If listening fails.
   * @see gnu.java.nio.VMChannel#accept()
   */
  public void listen(int backlog) throws IOException
  {
    listen(nfd.getNativeFD(), backlog);
  }

  /**
   * Native listen function. VMs without native support need not implement
   * this.
   *
   * @param fd The file descriptor integer.
   * @param backlog The listen backlog size.
   * @throws IOException
   */
  private static native void listen(int fd, int backlog) throws IOException;

  public void join(InetAddress group) throws IOException
  {
    if (group instanceof Inet4Address)
      join(nfd.getNativeFD(), group.getAddress());
    else if (group instanceof Inet6Address)
      join6(nfd.getNativeFD(), group.getAddress());
    else
      throw new IllegalArgumentException("unknown address type");
  }

  private static native void join(int fd, byte[] addr) throws IOException;

  private static native void join6(int fd, byte[] addr) throws IOException;

  public void leave(InetAddress group) throws IOException
  {
    if (group instanceof Inet4Address)
      leave(nfd.getNativeFD(), group.getAddress());
    else if (group instanceof Inet6Address)
      leave6(nfd.getNativeFD(), group.getAddress());
    else
      throw new IllegalArgumentException("unknown address type");
  }

  private static native void leave(int fd, byte[] addr) throws IOException;

  private static native void leave6(int fd, byte[] addr) throws IOException;

  public void joinGroup(InetSocketAddress addr, NetworkInterface netif)
    throws IOException
  {
    InetAddress address = addr.getAddress();

    if (address instanceof Inet4Address)
      joinGroup(nfd.getNativeFD(), address.getAddress(),
                netif != null ? netif.getName() : null);
    else if (address instanceof Inet6Address)
      joinGroup6(nfd.getNativeFD(), address.getAddress(),
                 netif != null ? netif.getName() : null);
    else
      throw new IllegalArgumentException("unknown address type");
  }

  private static native void joinGroup(int fd, byte[] addr, String ifname)
    throws IOException;

  private static native void joinGroup6(int fd, byte[] addr, String ifname)
    throws IOException;

  public void leaveGroup(InetSocketAddress addr, NetworkInterface netif)
    throws IOException
  {
    InetAddress address = addr.getAddress();
    if (address instanceof Inet4Address)
      leaveGroup(nfd.getNativeFD(), address.getAddress(),
                 netif != null ? netif.getName() : null);
    else if (address instanceof Inet6Address)
      leaveGroup6(nfd.getNativeFD(), address.getAddress(),
                 netif != null ? netif.getName() : null);
    else
      throw new IllegalArgumentException("unknown address type");
  }

  private static native void leaveGroup(int fd, byte[] addr, String ifname)
    throws IOException;

  private static native void leaveGroup6(int fd, byte[] addr, String ifname)
    throws IOException;


  public void shutdownInput() throws IOException
  {
    shutdownInput(nfd.getNativeFD());
  }

  private static native void shutdownInput(int native_fd) throws IOException;

  public void shutdownOutput() throws IOException
  {
    shutdownOutput(nfd.getNativeFD());
  }

  private static native void shutdownOutput(int native_fd) throws IOException;

  public void sendUrgentData(int data) throws IOException
  {
    sendUrgentData(nfd.getNativeFD(), data);
  }

  private static native void sendUrgentData(int natfive_fd, int data) throws IOException;

  public void close() throws IOException
  {
    nfd.close();
  }

  // Inner classes.

  /**
   * Our wrapper for the native file descriptor. In this implementation,
   * it is a simple wrapper around {@link VMChannel.State}, to simplify
   * management of the native state.
   */
  public final class State
  {
    private VMChannel.State channelFd;

    State()
    {
      channelFd = null;
    }

    public boolean isValid()
    {
      if (channelFd != null)
        return channelFd.isValid();
      return false;
    }

    public int getNativeFD() throws IOException
    {
      return channelFd.getNativeFD();
    }

    public void setChannelFD(final VMChannel.State nfd) throws IOException
    {
      if (this.channelFd != null && this.channelFd.isValid())
        throw new IOException("file descriptor already initialized");
      this.channelFd = nfd;
    }

    public void close() throws IOException
    {
      if (channelFd == null)
        throw new IOException("invalid file descriptor");
      channelFd.close();
    }

    protected void finalize() throws Throwable
    {
      try
        {
          if (isValid())
            close();
        }
      finally
        {
          super.finalize();
        }
    }
  }
}
