/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net;

import android.compat.annotation.UnsupportedAppUsage;
import android.system.ErrnoException;
import android.system.Int32Ref;
import android.system.Os;
import android.system.OsConstants;
import android.system.StructLinger;
import android.system.StructTimeval;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketOptions;

/**
 * Socket implementation used for android.net.LocalSocket and
 * android.net.LocalServerSocket. Supports only AF_LOCAL sockets.
 */
class LocalSocketImpl
{
    private SocketInputStream fis;
    private SocketOutputStream fos;
    private Object readMonitor = new Object();
    private Object writeMonitor = new Object();

    /** null if closed or not yet created */
    private FileDescriptor fd;
    /** whether fd is created internally */
    private boolean mFdCreatedInternally;

    // These fields are accessed by native code;
    /** file descriptor array received during a previous read */
    @UnsupportedAppUsage
    FileDescriptor[] inboundFileDescriptors;
    /** file descriptor array that should be written during next write */
    @UnsupportedAppUsage
    FileDescriptor[] outboundFileDescriptors;

    /**
     * An input stream for local sockets. Needed because we may
     * need to read ancillary data.
     */
    class SocketInputStream extends InputStream {
        /** {@inheritDoc} */
        @Override
        public int available() throws IOException {
            FileDescriptor myFd = fd;
            if (myFd == null) throw new IOException("socket closed");

            Int32Ref avail = new Int32Ref(0);
            try {
                Os.ioctlInt(myFd, OsConstants.FIONREAD, avail);
            } catch (ErrnoException e) {
                throw e.rethrowAsIOException();
            }
            return avail.value;
        }

        /** {@inheritDoc} */
        @Override
        public void close() throws IOException {
            LocalSocketImpl.this.close();
        }

        /** {@inheritDoc} */
        @Override
        public int read() throws IOException {
            int ret;
            synchronized (readMonitor) {
                FileDescriptor myFd = fd;
                if (myFd == null) throw new IOException("socket closed");

                ret = read_native(myFd);
                return ret;
            }
        }

        /** {@inheritDoc} */
        @Override
        public int read(byte[] b) throws IOException {
            return read(b, 0, b.length);
        }

        /** {@inheritDoc} */
        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            synchronized (readMonitor) {
                FileDescriptor myFd = fd;
                if (myFd == null) throw new IOException("socket closed");

                if (off < 0 || len < 0 || (off + len) > b.length ) {
                    throw new ArrayIndexOutOfBoundsException();
                }

                int ret = readba_native(b, off, len, myFd);

                return ret;
            }
        }
    }

    /**
     * An output stream for local sockets. Needed because we may
     * need to read ancillary data.
     */
    class SocketOutputStream extends OutputStream {
        /** {@inheritDoc} */
        @Override
        public void close() throws IOException {
            LocalSocketImpl.this.close();
        }

        /** {@inheritDoc} */
        @Override
        public void write (byte[] b) throws IOException {
            write(b, 0, b.length);
        }
        
        /** {@inheritDoc} */
        @Override
        public void write (byte[] b, int off, int len) throws IOException {
            synchronized (writeMonitor) {
                FileDescriptor myFd = fd;
                if (myFd == null) throw new IOException("socket closed");

                if (off < 0 || len < 0 || (off + len) > b.length ) {
                    throw new ArrayIndexOutOfBoundsException();
                }
                writeba_native(b, off, len, myFd);
            }
        }

        /** {@inheritDoc} */
        @Override
        public void write (int b) throws IOException {
            synchronized (writeMonitor) {
                FileDescriptor myFd = fd;
                if (myFd == null) throw new IOException("socket closed");
                write_native(b, myFd);
            }
        }
    }

    private native int read_native(FileDescriptor fd) throws IOException;
    private native int readba_native(byte[] b, int off, int len,
            FileDescriptor fd) throws IOException;
    private native void writeba_native(byte[] b, int off, int len,
            FileDescriptor fd) throws IOException;
    private native void write_native(int b, FileDescriptor fd)
            throws IOException;
    private native void connectLocal(FileDescriptor fd, String name,
            int namespace) throws IOException;
    private native void bindLocal(FileDescriptor fd, String name, int namespace)
            throws IOException;
    private native Credentials getPeerCredentials_native(
            FileDescriptor fd) throws IOException;

    /**
     * Create a new instance.
     */
    @UnsupportedAppUsage
    /*package*/ LocalSocketImpl()
    {
    }

    /**
     * Create a new instance from a file descriptor representing
     * a bound socket. The state of the file descriptor is not checked here
     *  but the caller can verify socket state by calling listen().
     *
     * @param fd non-null; bound file descriptor
     */
    /*package*/ LocalSocketImpl(FileDescriptor fd)
    {
        this.fd = fd;
    }

    public String toString() {
        return super.toString() + " fd:" + fd;
    }

    /**
     * Creates a socket in the underlying OS.
     *
     * @param sockType either {@link LocalSocket#SOCKET_DGRAM}, {@link LocalSocket#SOCKET_STREAM}
     * or {@link LocalSocket#SOCKET_SEQPACKET}
     * @throws IOException
     */
    public void create(int sockType) throws IOException {
        if (fd != null) {
            throw new IOException("LocalSocketImpl already has an fd");
        }

        int osType;
        switch (sockType) {
            case LocalSocket.SOCKET_DGRAM:
                osType = OsConstants.SOCK_DGRAM;
                break;
            case LocalSocket.SOCKET_STREAM:
                osType = OsConstants.SOCK_STREAM;
                break;
            case LocalSocket.SOCKET_SEQPACKET:
                osType = OsConstants.SOCK_SEQPACKET;
                break;
            default:
                throw new IllegalStateException("unknown sockType");
        }
        try {
            fd = Os.socket(OsConstants.AF_UNIX, osType, 0);
            mFdCreatedInternally = true;
        } catch (ErrnoException e) {
            e.rethrowAsIOException();
        }
    }

    /**
     * Closes the socket.
     *
     * @throws IOException
     */
    public void close() throws IOException {
        synchronized (LocalSocketImpl.this) {
            if ((fd == null) || (mFdCreatedInternally == false)) {
                fd = null;
                return;
            }
            try {
                Os.close(fd);
            } catch (ErrnoException e) {
                e.rethrowAsIOException();
            }
            fd = null;
        }
    }

    /** note timeout presently ignored */
    protected void connect(LocalSocketAddress address, int timeout)
                        throws IOException
    {        
        if (fd == null) {
            throw new IOException("socket not created");
        }

        connectLocal(fd, address.getName(), address.getNamespace().getId());
    }

    /**
     * Binds this socket to an endpoint name. May only be called on an instance
     * that has not yet been bound.
     *
     * @param endpoint endpoint address
     * @throws IOException
     */
    public void bind(LocalSocketAddress endpoint) throws IOException
    {
        if (fd == null) {
            throw new IOException("socket not created");
        }

        bindLocal(fd, endpoint.getName(), endpoint.getNamespace().getId());
    }

    protected void listen(int backlog) throws IOException
    {
        if (fd == null) {
            throw new IOException("socket not created");
        }
        try {
            Os.listen(fd, backlog);
        } catch (ErrnoException e) {
            throw e.rethrowAsIOException();
        }
    }

    /**
     * Accepts a new connection to the socket. Blocks until a new
     * connection arrives.
     *
     * @param s a socket that will be used to represent the new connection.
     * @throws IOException
     */
    protected void accept(LocalSocketImpl s) throws IOException {
        if (fd == null) {
            throw new IOException("socket not created");
        }

        try {
            s.fd = Os.accept(fd, null /* address */);
            s.mFdCreatedInternally = true;
        } catch (ErrnoException e) {
            throw e.rethrowAsIOException();
        }
    }

    /**
     * Retrieves the input stream for this instance.
     *
     * @return input stream
     * @throws IOException if socket has been closed or cannot be created.
     */
    protected InputStream getInputStream() throws IOException
    {
        if (fd == null) {
            throw new IOException("socket not created");
        }

        synchronized (this) {
            if (fis == null) {
                fis = new SocketInputStream();
            }

            return fis;
        }
    }

    /**
     * Retrieves the output stream for this instance.
     *
     * @return output stream
     * @throws IOException if socket has been closed or cannot be created.
     */
    protected OutputStream getOutputStream() throws IOException
    { 
        if (fd == null) {
            throw new IOException("socket not created");
        }

        synchronized (this) {
            if (fos == null) {
                fos = new SocketOutputStream();
            }

            return fos;
        }
    }

    /**
     * Returns the number of bytes available for reading without blocking.
     *
     * @return >= 0 count bytes available
     * @throws IOException
     */
    protected int available() throws IOException
    {
        return getInputStream().available();
    }

    /**
     * Shuts down the input side of the socket.
     *
     * @throws IOException
     */
    protected void shutdownInput() throws IOException
    {
        if (fd == null) {
            throw new IOException("socket not created");
        }

        try {
            Os.shutdown(fd, OsConstants.SHUT_RD);
        } catch (ErrnoException e) {
            throw e.rethrowAsIOException();
        }
    }

    /**
     * Shuts down the output side of the socket.
     *
     * @throws IOException
     */
    protected void shutdownOutput() throws IOException
    {
        if (fd == null) {
            throw new IOException("socket not created");
        }

        try {
            Os.shutdown(fd, OsConstants.SHUT_WR);
        } catch (ErrnoException e) {
            throw e.rethrowAsIOException();
        }
    }

    protected FileDescriptor getFileDescriptor()
    {
        return fd;
    }

    protected boolean supportsUrgentData()
    {
        return false;
    }

    protected void sendUrgentData(int data) throws IOException
    {
        throw new RuntimeException ("not impled");
    }

    public Object getOption(int optID) throws IOException
    {
        if (fd == null) {
            throw new IOException("socket not created");
        }

        try {
            Object toReturn;
            switch (optID) {
                case SocketOptions.SO_TIMEOUT:
                    StructTimeval timeval = Os.getsockoptTimeval(fd, OsConstants.SOL_SOCKET,
                            OsConstants.SO_SNDTIMEO);
                    toReturn = (int) timeval.toMillis();
                    break;
                case SocketOptions.SO_RCVBUF:
                case SocketOptions.SO_SNDBUF:
                case SocketOptions.SO_REUSEADDR:
                    int osOpt = javaSoToOsOpt(optID);
                    toReturn = Os.getsockoptInt(fd, OsConstants.SOL_SOCKET, osOpt);
                    break;
                case SocketOptions.SO_LINGER:
                    StructLinger linger=
                            Os.getsockoptLinger(fd, OsConstants.SOL_SOCKET, OsConstants.SO_LINGER);
                    if (!linger.isOn()) {
                        toReturn = -1;
                    } else {
                        toReturn = linger.l_linger;
                    }
                    break;
                case SocketOptions.TCP_NODELAY:
                    toReturn = Os.getsockoptInt(fd, OsConstants.IPPROTO_TCP,
                            OsConstants.TCP_NODELAY);
                    break;
                default:
                    throw new IOException("Unknown option: " + optID);
            }
            return toReturn;
        } catch (ErrnoException e) {
            throw e.rethrowAsIOException();
        }
    }

    public void setOption(int optID, Object value)
            throws IOException {

        if (fd == null) {
            throw new IOException("socket not created");
        }

        /*
         * Boolean.FALSE is used to disable some options, so it
         * is important to distinguish between FALSE and unset.
         * We define it here that -1 is unset, 0 is FALSE, and 1
         * is TRUE.
         */
        int boolValue = -1;
        int intValue = 0;
        if (value instanceof Integer) {
            intValue = (Integer)value;
        } else if (value instanceof Boolean) {
            boolValue = ((Boolean) value)? 1 : 0;
        } else {
            throw new IOException("bad value: " + value);
        }

        try {
            switch (optID) {
                case SocketOptions.SO_LINGER:
                    StructLinger linger = new StructLinger(boolValue, intValue);
                    Os.setsockoptLinger(fd, OsConstants.SOL_SOCKET, OsConstants.SO_LINGER, linger);
                    break;
                case SocketOptions.SO_TIMEOUT:
                    // The option must set both send and receive timeouts.
                    // Note: The incoming timeout value is in milliseconds.
                    StructTimeval timeval = StructTimeval.fromMillis(intValue);
                    Os.setsockoptTimeval(fd, OsConstants.SOL_SOCKET, OsConstants.SO_RCVTIMEO,
                            timeval);
                    Os.setsockoptTimeval(fd, OsConstants.SOL_SOCKET, OsConstants.SO_SNDTIMEO,
                            timeval);
                    break;
                case SocketOptions.SO_RCVBUF:
                case SocketOptions.SO_SNDBUF:
                case SocketOptions.SO_REUSEADDR:
                    int osOpt = javaSoToOsOpt(optID);
                    Os.setsockoptInt(fd, OsConstants.SOL_SOCKET, osOpt, intValue);
                    break;
                case SocketOptions.TCP_NODELAY:
                    Os.setsockoptInt(fd, OsConstants.IPPROTO_TCP, OsConstants.TCP_NODELAY,
                            intValue);
                    break;
                default:
                    throw new IOException("Unknown option: " + optID);
            }
        } catch (ErrnoException e) {
            throw e.rethrowAsIOException();
        }
    }

    /**
     * Enqueues a set of file descriptors to send to the peer. The queue
     * is one deep. The file descriptors will be sent with the next write
     * of normal data, and will be delivered in a single ancillary message.
     * See "man 7 unix" SCM_RIGHTS on a desktop Linux machine.
     *
     * @param fds non-null; file descriptors to send.
     * @throws IOException
     */
    public void setFileDescriptorsForSend(FileDescriptor[] fds) {
        synchronized(writeMonitor) {
            outboundFileDescriptors = fds;
        }
    }

    /**
     * Retrieves a set of file descriptors that a peer has sent through
     * an ancillary message. This method retrieves the most recent set sent,
     * and then returns null until a new set arrives.
     * File descriptors may only be passed along with regular data, so this
     * method can only return a non-null after a read operation.
     *
     * @return null or file descriptor array
     * @throws IOException
     */
    public FileDescriptor[] getAncillaryFileDescriptors() throws IOException {
        synchronized(readMonitor) {
            FileDescriptor[] result = inboundFileDescriptors;

            inboundFileDescriptors = null;
            return result;
        }
    }

    /**
     * Retrieves the credentials of this socket's peer. Only valid on
     * connected sockets.
     *
     * @return non-null; peer credentials
     * @throws IOException
     */
    public Credentials getPeerCredentials() throws IOException {
        return getPeerCredentials_native(fd);
    }

    /**
     * Retrieves the socket name from the OS.
     *
     * @return non-null; socket name
     * @throws IOException on failure
     */
    public LocalSocketAddress getSockAddress() throws IOException {
        // This method has never been implemented.
        return null;
    }

    @Override
    protected void finalize() throws IOException {
        close();
    }

    private static int javaSoToOsOpt(int optID) {
        switch (optID) {
            case SocketOptions.SO_SNDBUF:
                return OsConstants.SO_SNDBUF;
            case SocketOptions.SO_RCVBUF:
                return OsConstants.SO_RCVBUF;
            case SocketOptions.SO_REUSEADDR:
                return OsConstants.SO_REUSEADDR;
            default:
                throw new UnsupportedOperationException("Unknown option: " + optID);
        }
    }
}
