/* VMChannel.java -- Native interface suppling channel operations.
   Copyright (C) 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.nio;

import gnu.classpath.Configuration;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;

/**
 * Native interface to support configuring of channel to run in a non-blocking
 * manner and support scatter/gather io operations.
 * 
 * @author Michael Barker <mike@middlesoft.co.uk>
 *
 */
public final class VMChannel
{
  /**
   * Our reference implementation uses an integer to store the native
   * file descriptor. Implementations without such support 
   */
  private final State nfd;
  
  private Kind kind;
  
  public VMChannel()
  {
    // XXX consider adding security check here, so only Classpath
    // code may create instances.
    this.nfd = new State();
    kind = Kind.OTHER;
  }
  
  /**
   * This constructor is used by the POSIX reference implementation;
   * other virtual machines need not support it.
   * 
   * <strong>Important:</strong> do not call this in library code that is
   * not specific to Classpath's reference implementation.
   * 
   * @param native_fd The native file descriptor integer.
   * @throws IOException
   */
  VMChannel(final int native_fd) throws IOException
  {
    this();
    this.nfd.setNativeFD(native_fd);
  }
  
  public State getState()
  {
    return nfd;
  }

  static
  {
    // load the shared library needed for native methods.
    if (Configuration.INIT_LOAD_LIBRARY)
      {
        System.loadLibrary ("javanio");
      }
    initIDs();
  }
  
  public static VMChannel getStdin() throws IOException
  {
    return new VMChannel(stdin_fd());
  }
  
  public static VMChannel getStdout() throws IOException
  {
    return new VMChannel(stdout_fd());
  }
  
  public static VMChannel getStderr() throws IOException
  {
    return new VMChannel(stderr_fd());
  }
  
  private static native int stdin_fd();
  private static native int stdout_fd();
  private static native int stderr_fd();
  
  /**
   * Set the file descriptor to have the required blocking
   * setting.
   * 
   * @param blocking The blocking flag to set.
   */
  public void setBlocking(boolean blocking) throws IOException
  {
    setBlocking(nfd.getNativeFD(), blocking);
  }
  
  private static native void setBlocking(int fd, boolean blocking)
    throws IOException;
  
  public int available() throws IOException
  {
    return available(nfd.getNativeFD());
  }
  
  private static native int available(int native_fd) throws IOException;

  /**
   * Reads a byte buffer directly using the supplied file descriptor.
   * 
   * @param dst Direct Byte Buffer to read to.
   * @return Number of bytes read.
   * @throws IOException If an error occurs or dst is not a direct buffers. 
   */
  public int read(ByteBuffer dst)
    throws IOException
  {
    return read(nfd.getNativeFD(), dst);
  }
  
  private static native int read(int fd, ByteBuffer dst) throws IOException;
  
  /**
   * Read a single byte.
   *
   * @return The byte read, or -1 on end of file.
   * @throws IOException
   */
  public int read() throws IOException
  {
    return read(nfd.getNativeFD());
  }
  
  private static native int read(int fd) throws IOException;
  
  /**
   * Reads into byte buffers directly using the supplied file descriptor.
   * Assumes that the buffer list contains DirectBuffers.  Will perform a
   * scattering read.
   * 
   * @param dsts An array direct byte buffers.
   * @param offset Index of the first buffer to read to.
   * @param length The number of buffers to read to.
   * @return Number of bytes read.
   * @throws IOException If an error occurs or the dsts are not direct buffers. 
   */
  public long readScattering(ByteBuffer[] dsts, int offset, int length)
    throws IOException
  {
    if (offset + length > dsts.length)
      throw new IndexOutOfBoundsException("offset + length > dsts.length");

    return readScattering(nfd.getNativeFD(), dsts, offset, length);
  }
  
  private static native long readScattering(int fd, ByteBuffer[] dsts,
                                            int offset, int length)
    throws IOException;
  
  /**
   * Receive a datagram on this channel, returning the host address
   * that sent the datagram.
   *
   * @param dst Where to store the datagram.
   * @return The host address that sent the datagram.
   * @throws IOException
   */
  public SocketAddress receive(ByteBuffer dst) throws IOException
  {
    if (kind != Kind.SOCK_DGRAM)
      throw new SocketException("not a datagram socket");
    ByteBuffer hostPort = ByteBuffer.allocateDirect(18);
    int hostlen = receive(nfd.getNativeFD(), dst, hostPort);
    if (hostlen == 0)
      return null;
    if (hostlen == 4) // IPv4
      {
        byte[] addr = new byte[4];
        hostPort.get(addr);
        int port = hostPort.getShort() & 0xFFFF;
        return new InetSocketAddress(Inet4Address.getByAddress(addr), port);
      }
    if (hostlen == 16) // IPv6
      {
        byte[] addr = new byte[16];
        hostPort.get(addr);
        int port = hostPort.getShort() & 0xFFFF;
        return new InetSocketAddress(Inet6Address.getByAddress(addr), port);
      }
    
    throw new SocketException("host address received with invalid length: "
                              + hostlen);
  }
  
  private static native int receive (int fd, ByteBuffer dst, ByteBuffer address)
    throws IOException;

  /**
   * Writes from a direct byte bufer using the supplied file descriptor.
   * Assumes the buffer is a DirectBuffer.
   * 
   * @param src The source buffer.
   * @return Number of bytes written.
   * @throws IOException
   */
  public int write(ByteBuffer src) throws IOException
  {
    return write(nfd.getNativeFD(), src);
  }
  
  private native int write(int fd, ByteBuffer src) throws IOException;

  /**
   * Writes from byte buffers directly using the supplied file descriptor.
   * Assumes the that buffer list constains DirectBuffers.  Will perform
   * as gathering write.
   * 
   * @param srcs
   * @param offset
   * @param length
   * @return Number of bytes written.
   * @throws IOException
   */
  public long writeGathering(ByteBuffer[] srcs, int offset, int length)
    throws IOException
  {
    if (offset + length > srcs.length)
      throw new IndexOutOfBoundsException("offset + length > srcs.length");
    
    // A gathering write is limited to 16 buffers; when writing, ensure
    // that we have at least one buffer with something in it in the 16
    // buffer window starting at offset.
    while (!srcs[offset].hasRemaining() && offset < srcs.length)
      offset++;
    
    // There are no buffers with anything to write.
    if (offset == srcs.length)
      return 0;

    // If we advanced `offset' so far that we don't have `length'
    // buffers left, reset length to only the remaining buffers.
    if (length > srcs.length - offset)
      length = srcs.length - offset;

    return writeGathering(nfd.getNativeFD(), srcs, offset, length);
  }
  
  private native long writeGathering(int fd, ByteBuffer[] srcs,
                                     int offset, int length)
    throws IOException;
  
  /**
   * Send a datagram to the given address.
   *
   * @param src The source buffer.
   * @param dst The destination address.
   * @return The number of bytes written.
   * @throws IOException
   */
  public int send(ByteBuffer src, InetSocketAddress dst)
    throws IOException
  {
    InetAddress addr = dst.getAddress();
    if (addr == null)
      throw new NullPointerException();
    if (addr instanceof Inet4Address)
      return send(nfd.getNativeFD(), src, addr.getAddress(), dst.getPort());
    else if (addr instanceof Inet6Address)
      return send6(nfd.getNativeFD(), src, addr.getAddress(), dst.getPort());
    else
      throw new SocketException("unrecognized inet address type");
  }
  
  // Send to an IPv4 address.
  private static native int send(int fd, ByteBuffer src, byte[] addr, int port)
    throws IOException;
  
  // Send to an IPv6 address.
  private static native int send6(int fd, ByteBuffer src, byte[] addr, int port)
    throws IOException;
  
  /**
   * Write a single byte.
   *
   * @param b The byte to write.
   * @throws IOException
   */
  public void write(int b) throws IOException
  {
    write(nfd.getNativeFD(), b);
  }
  
  private static native void write(int fd, int b) throws IOException;
  
  private native static void initIDs();

  // Network (socket) specific methods.
  
  /**
   * Create a new socket. This method will initialize the native file
   * descriptor state of this instance.
   *
   * @param stream Whether or not to create a streaming socket, or a datagram
   *  socket.
   * @throws IOException If creating a new socket fails, or if this
   *  channel already has its native descriptor initialized.
   */
  public void initSocket(boolean stream) throws IOException
  {
    if (nfd.isValid())
      throw new IOException("native FD already initialized");
    if (stream)
      kind = Kind.SOCK_STREAM;
    else
      kind = Kind.SOCK_DGRAM;
    nfd.setNativeFD(socket(stream));
  }
  
  /**
   * Create a new socket, returning the native file descriptor.
   *
   * @param stream Set to true for streaming sockets; false for datagrams.
   * @return The native file descriptor.
   * @throws IOException If creating the socket fails.
   */
  private static native int socket(boolean stream) throws IOException;

  /**
   * Connect the underlying socket file descriptor to the remote host.
   *
   * @param saddr The address to connect to.
   * @param timeout The connect timeout to use for blocking connects.
   * @return True if the connection succeeded; false if the file descriptor
   *  is in non-blocking mode and the connection did not immediately
   *  succeed.
   * @throws IOException If an error occurs while connecting.
   */
  public boolean connect(InetSocketAddress saddr, int timeout)
    throws SocketException
  {
    int fd;

    InetAddress addr = saddr.getAddress();
 
    // Translates an IOException into a SocketException to conform
    // to the throws clause.
    try
      {
        fd = nfd.getNativeFD();
      }
    catch (IOException ioe)
      {
        throw new SocketException(ioe.getMessage());
      }

    if (addr instanceof Inet4Address)
      return connect(fd, addr.getAddress(), saddr.getPort(),
                     timeout);
    if (addr instanceof Inet6Address)
      return connect6(fd, addr.getAddress(), saddr.getPort(),
                      timeout);
    throw new SocketException("unsupported internet address");
  }
  
  private static native boolean connect(int fd, byte[] addr, int port, int timeout)
    throws SocketException;
  
  private static native boolean connect6(int fd, byte[] addr, int port, int timeout)
    throws SocketException;
  
  /**
   * Disconnect this channel, if it is a datagram socket. Disconnecting
   * a datagram channel will disassociate it from any address, so the
   * socket will remain open, but can send and receive datagrams from
   * any address.
   *
   * @throws IOException If disconnecting this channel fails, or if this
   *  channel is not a datagram channel.
   */
  public void disconnect() throws IOException
  {
    if (kind != Kind.SOCK_DGRAM)
      throw new IOException("can only disconnect datagram channels");
    disconnect(nfd.getNativeFD());
  }
  
  private static native void disconnect(int fd) throws IOException;
  
  public InetSocketAddress getLocalAddress() throws IOException
  {
    if (!nfd.isValid())
      return null;
    ByteBuffer name = ByteBuffer.allocateDirect(18);
    int namelen = getsockname(nfd.getNativeFD(), name);
    if (namelen == 0) // not bound
      return null; // XXX return some wildcard?
    if (namelen == 4)
      {
        byte[] addr = new byte[4];
        name.get(addr);
        int port = name.getShort() & 0xFFFF;
        return new InetSocketAddress(Inet4Address.getByAddress(addr), port);
      }
    if (namelen == 16)
      {
        byte[] addr = new byte[16];
        name.get(addr);
        int port = name.getShort() & 0xFFFF;
        return new InetSocketAddress(Inet6Address.getByAddress(addr), port);
      }
    throw new SocketException("invalid address length");
  }
  
  private static native int getsockname(int fd, ByteBuffer name)
    throws IOException;

  /**
   * Returns the socket address of the remote peer this channel is connected
   * to, or null if this channel is not yet connected.
   *
   * @return The peer address.
   * @throws IOException
   */
  public InetSocketAddress getPeerAddress() throws IOException
  {
    if (!nfd.isValid())
      return null;
    ByteBuffer name = ByteBuffer.allocateDirect(18);
    int namelen = getpeername (nfd.getNativeFD(), name);
    if (namelen == 0) // not connected yet
      return null;
    if (namelen == 4) // IPv4
      {
        byte[] addr = new byte[4];
        name.get(addr);
        int port = name.getShort() & 0xFFFF;
        return new InetSocketAddress(Inet4Address.getByAddress(addr), port);
      }
    else if (namelen == 16) // IPv6
      {
        byte[] addr = new byte[16];
        name.get(addr);
        int port = name.getShort() & 0xFFFF;
        return new InetSocketAddress(Inet6Address.getByAddress(addr), port);
      }
    throw new SocketException("invalid address length");
  }
  
  /*
   * The format here is the peer address, followed by the port number.
   * The returned value is the length of the peer address; thus, there
   * will be LEN + 2 valid bytes put into NAME.
   */
  private static native int getpeername(int fd, ByteBuffer name)
    throws IOException;
  
  /**
   * Accept an incoming connection, returning a new VMChannel, or null
   * if the channel is nonblocking and no connection is pending.
   *
   * @return The accepted connection, or null.
   * @throws IOException If an IO error occurs.
   */
  public VMChannel accept() throws IOException
  {
    int new_fd = accept(nfd.getNativeFD());
    if (new_fd == -1) // non-blocking accept had no pending connection
      return null;
    return new VMChannel(new_fd);
  }
  
  private static native int accept(int native_fd) throws IOException;

  // File-specific methods.
  
  /**
   * Open a file at PATH, initializing the native state to operate on
   * that open file.
   * 
   * @param path The absolute file path.
   * @throws IOException If the file cannot be opened, or if this 
   *  channel was previously initialized.
   */
  public void openFile(String path, int mode) throws IOException
  {
    if (nfd.isValid() || nfd.isClosed())
      throw new IOException("can't reinitialize this channel");
    int fd = open(path, mode);
    nfd.setNativeFD(fd);
    kind = Kind.FILE;
  }
  
  private static native int open(String path, int mode) throws IOException;
  
  public long position() throws IOException
  {
    if (kind != Kind.FILE)
      throw new IOException("not a file");
    return position(nfd.getNativeFD());
  }
  
  private static native long position(int fd) throws IOException;
  
  public void seek(long pos) throws IOException
  {
    if (kind != Kind.FILE)
      throw new IOException("not a file");
    seek(nfd.getNativeFD(), pos);
  }
  
  private static native void seek(int fd, long pos) throws IOException;

  public void truncate(long length) throws IOException
  {
    if (kind != Kind.FILE)
      throw new IOException("not a file");
    truncate(nfd.getNativeFD(), length);
  }
  
  private static native void truncate(int fd, long len) throws IOException;
  
  public boolean lock(long pos, long len, boolean shared, boolean wait)
    throws IOException
  {
    if (kind != Kind.FILE)
      throw new IOException("not a file");
    return lock(nfd.getNativeFD(), pos, len, shared, wait);
  }
  
  private static native boolean lock(int fd, long pos, long len,
                                     boolean shared, boolean wait)
    throws IOException;
  
  public void unlock(long pos, long len) throws IOException
  {
    if (kind != Kind.FILE)
      throw new IOException("not a file");
    unlock(nfd.getNativeFD(), pos, len);
  }
  
  private static native void unlock(int fd, long pos, long len) throws IOException;
  
  public long size() throws IOException
  {
    if (kind != Kind.FILE)
      throw new IOException("not a file");
    return size(nfd.getNativeFD());
  }
  
  private static native long size(int fd) throws IOException;

  public MappedByteBuffer map(char mode, long position, int size)
    throws IOException
  {
    if (kind != Kind.FILE)
      throw new IOException("not a file");
    return map(nfd.getNativeFD(), mode, position, size);
  }
  
  private static native MappedByteBuffer map(int fd, char mode,
                                             long position, int size)
    throws IOException;
  
  public boolean flush(boolean metadata) throws IOException
  {
    if (kind != Kind.FILE)
      throw new IOException("not a file");
    return flush(nfd.getNativeFD(), metadata);
  }
  
  private static native boolean flush(int fd, boolean metadata) throws IOException;
  
  // Close.
  
  /**
   * Close this socket. The socket is also automatically closed when this
   * object is finalized.
   *
   * @throws IOException If closing the socket fails, or if this object has
   *  no open socket.
   */
  public void close() throws IOException
  {
    nfd.close();
  }
  
  static native void close(int native_fd) throws IOException;
  
  /**
   * <p>Provides a simple mean for the JNI code to find out whether the
   * current thread was interrupted by a call to Thread.interrupt().</p>
   * 
   * @return
   */
  static boolean isThreadInterrupted()
  {
    return Thread.currentThread().isInterrupted();
  }

  // Inner classes.
  
  /**
   * A wrapper for a native file descriptor integer. This tracks the state
   * of an open file descriptor, and ensures that 
   * 
   * This class need not be fully supported by virtual machines; if a
   * virtual machine does not use integer file descriptors, or does and
   * wishes to hide that, then the methods of this class may be stubbed out.
   * 
   * System-specific classes that depend on access to native file descriptor
   * integers SHOULD declare this fact.
   */
  public final class State
  {
    private int native_fd;
    private boolean valid;
    private boolean closed;
    
    State()
    {
      native_fd = -1;
      valid = false;
      closed = false;
    }
    
    public boolean isValid()
    {
      return valid;
    }
    
    public boolean isClosed()
    {
      return closed;
    }
    
    public int getNativeFD() throws IOException
    {
      if (!valid)
        throw new IOException("invalid file descriptor");
      return native_fd;
    }
    
    void setNativeFD(final int native_fd) throws IOException
    {
      if (valid)
        throw new IOException("file descriptor already initialized");
      this.native_fd = native_fd;
      valid = true;
    }
    
    public void close() throws IOException
    {
      if (!valid)
        throw new IOException("invalid file descriptor");
      try
        {
          VMChannel.close(native_fd);
        }
      finally
        {
          valid = false;
          closed = true;
        }
    }
    
    public String toString()
    {
      if (closed)
        return "<<closed>>";
      if (!valid)
        return "<<invalid>>";
      return String.valueOf(native_fd);
    }
    
    protected void finalize() throws Throwable
    {
      try
        {
          if (valid)
            close();
        }
      finally
        {
          super.finalize();
        }
    }
  }
  
  /**
   * An enumeration of possible kinds of channel.
   */
  static class Kind // XXX enum
  {
    /** A streaming (TCP) socket. */
    static final Kind SOCK_STREAM = new Kind();
    
    /** A datagram (UDP) socket. */
    static final Kind SOCK_DGRAM = new Kind();
    
    /** A file. */
    static final Kind FILE = new Kind();
    
    /** Something else; not a socket or file. */
    static final Kind OTHER = new Kind();
    
    private Kind() { }
  }
}
