/*
 * Copyright (C) 2014 The Android Open Source Project
 * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.net;

import android.system.ErrnoException;

import java.io.IOException;
import java.io.FileDescriptor;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import libcore.io.AsynchronousCloseMonitor;
import libcore.io.IoBridge;
import libcore.io.IoUtils;
import libcore.io.Libcore;

import jdk.net.*;

import static android.system.OsConstants.AF_INET6;
import static android.system.OsConstants.AF_UNIX;
import static android.system.OsConstants.EAGAIN;
import static android.system.OsConstants.EBADF;
import static android.system.OsConstants.EINVAL;
import static android.system.OsConstants.MSG_OOB;
import static android.system.OsConstants.POLLERR;
import static android.system.OsConstants.POLLIN;
import static android.system.OsConstants.SOCK_DGRAM;
import static android.system.OsConstants.SOCK_STREAM;
import static android.system.OsConstants.SHUT_RDWR;
import static sun.net.ExtendedOptionsImpl.*;

// Android-changed: Rewritten to use android.system POSIX calls and assume AF_INET6.
/*
 * On Unix systems we simply delegate to native methods.
 *
 * @author Chris Hegarty
 */

class PlainSocketImpl extends AbstractPlainSocketImpl
{
    /**
     * Constructs an empty instance.
     */
    PlainSocketImpl() {
        this(new FileDescriptor());
    }

    /**
     * Constructs an instance with the given file descriptor.
     */
    PlainSocketImpl(FileDescriptor fd) {
        this.fd = fd;
    }

    protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
        if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
            super.setOption(name, value);
        } else {
            if (isClosedOrPending()) {
                throw new SocketException("Socket closed");
            }
            checkSetOptionPermission(name);
            checkValueType(value, SocketFlow.class);
            setFlowOption(getFileDescriptor(), (SocketFlow)value);
        }
    }

    protected <T> T getOption(SocketOption<T> name) throws IOException {
        if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
            return super.getOption(name);
        }
        if (isClosedOrPending()) {
            throw new SocketException("Socket closed");
        }
        checkGetOptionPermission(name);
        SocketFlow flow = SocketFlow.create();
        getFlowOption(getFileDescriptor(), flow);
        return (T)flow;
    }

    protected void socketSetOption(int opt, Object val) throws SocketException {
        try {
            socketSetOption0(opt, val);
        } catch (SocketException se) {
            if (socket == null || !socket.isConnected())
                throw se;
        }
    }

    void socketCreate(boolean isStream) throws IOException {
        // The fd object must not change after calling bind, because we rely on this undocumented
        // behaviour. See libcore.java.net.SocketTest#testFileDescriptorStaysSame.
        fd.setInt$(IoBridge.socket(AF_INET6, isStream ? SOCK_STREAM : SOCK_DGRAM, 0).getInt$());

        if (serverSocket != null) {
            IoUtils.setBlocking(fd, false);
            IoBridge.setSocketOption(fd, SO_REUSEADDR, true);
        }
    }

    void socketConnect(InetAddress address, int port, int timeout) throws IOException {
        if (fd == null || !fd.valid()) {
            throw new SocketException("Socket closed");
        }

        IoBridge.connect(fd, address, port, timeout);

        this.address = address;
        this.port = port;

        if (localport == 0) {
            // If socket is pending close, fd becomes an AF_UNIX socket and calling
            // getLocalInetSocketAddress will fail.
            // http://b/34645743
            if (!isClosedOrPending()) {
                localport = IoBridge.getLocalInetSocketAddress(fd).getPort();
            }
        }
    }

    void socketBind(InetAddress address, int port) throws IOException {
        if (fd == null || !fd.valid()) {
            throw new SocketException("Socket closed");
        }

        IoBridge.bind(fd, address, port);

        this.address = address;
        if (port == 0) {
            // Now that we're a connected socket, let's extract the port number that the system
            // chose for us and store it in the Socket object.
            localport = IoBridge.getLocalInetSocketAddress(fd).getPort();
        } else {
            localport = port;
        }
    }

    void socketListen(int count) throws IOException {
        if (fd == null || !fd.valid()) {
            throw new SocketException("Socket closed");
        }

        try {
            Libcore.os.listen(fd, count);
        } catch (ErrnoException errnoException) {
            throw errnoException.rethrowAsSocketException();
        }
    }

    void socketAccept(SocketImpl s) throws IOException {
        if (fd == null || !fd.valid()) {
            throw new SocketException("Socket closed");
        }

        // poll() with a timeout of 0 means "poll for zero millis", but a Socket timeout == 0 means
        // "wait forever". When timeout == 0 we pass -1 to poll.
        if (timeout <= 0) {
            IoBridge.poll(fd, POLLIN | POLLERR, -1);
        } else {
            IoBridge.poll(fd, POLLIN | POLLERR, timeout);
        }

        InetSocketAddress peerAddress = new InetSocketAddress();
        try {
            FileDescriptor newfd = Libcore.os.accept(fd, peerAddress);

            s.fd.setInt$(newfd.getInt$());
            s.address = peerAddress.getAddress();
            s.port = peerAddress.getPort();
        } catch (ErrnoException errnoException) {
            if (errnoException.errno == EAGAIN) {
                throw new SocketTimeoutException(errnoException);
            } else if (errnoException.errno == EINVAL || errnoException.errno == EBADF) {
                throw new SocketException("Socket closed");
            }
            errnoException.rethrowAsSocketException();
        }

        s.localport = IoBridge.getLocalInetSocketAddress(s.fd).getPort();
    }

    int socketAvailable() throws IOException {
        return IoBridge.available(fd);
    }

    void socketClose0(boolean useDeferredClose) throws IOException {
        if (fd == null || !fd.valid()) {
            throw new SocketException("socket already closed");
        }

        FileDescriptor markerFD = null;
        if (useDeferredClose) {
            markerFD = getMarkerFD();
        }

        if (useDeferredClose && markerFD != null) {
            try {
                Libcore.os.dup2(markerFD, fd.getInt$());
                Libcore.os.close(markerFD);

                // This effectively closes the socket, needs to signal threads that blocks on this
                // file descriptor.
                AsynchronousCloseMonitor.signalBlockedThreads(fd);
            } catch (ErrnoException errnoException) {
                // close should not throw
            }
        } else {
            // If requested or a markerFD cannot be created, a non-deferred close is performed
            // instead.
            IoBridge.closeAndSignalBlockedThreads(fd);
        }
    }

    /*
     * Create the marker file descriptor by establishing a loopback connection which we shutdown but
     * do not close the fd. The result is an fd that can be used for read/write.
     *
     * The purpose is to keep hold of the raw fd handle until we are sure it is not used in any
     * thread. Otherwise if we close the file descriptor directly, the system might reuse the raw fd
     * number and threads holding old fd value might behave incorrectly.
     */
    private FileDescriptor getMarkerFD() throws SocketException {
        FileDescriptor fd1 = new FileDescriptor();
        FileDescriptor fd2 = new FileDescriptor();
        try {
            Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd1, fd2);

            // Shutdown fd1, any reads to this fd will get EOF; any writes will get an error.
            Libcore.os.shutdown(fd1, SHUT_RDWR);
            Libcore.os.close(fd2);
        } catch (ErrnoException errnoException) {
            // We might have reached the maximum file descriptor number and socketpair(2) would
            // fail. In this case, return null and let caller to fall back to an alternative method
            // that does not allocate more file descriptors.
            return null;
        }
        return fd1;
    }

    void socketShutdown(int howto) throws IOException {
        try {
            Libcore.os.shutdown(fd, howto);
        } catch (ErrnoException errnoException) {
            throw errnoException.rethrowAsIOException();
        }
    }

    void socketSetOption0(int cmd, Object value) throws SocketException {
        // OpenJDK does not set SO_TIMEOUT on Linux.
        if (cmd == SO_TIMEOUT) {
            return;
        }

        IoBridge.setSocketOption(fd, cmd, value);
    }

    Object socketGetOption(int opt) throws SocketException {
        return IoBridge.getSocketOption(fd, opt);
    }

    void socketSendUrgentData(int data) throws IOException {
        if (fd == null || !fd.valid()) {
            throw new SocketException("Socket closed");
        }

        try {
            byte[] buffer = new byte[] { (byte) data };
            Libcore.os.sendto(fd, buffer, 0, 1, MSG_OOB, null, 0);
        } catch (ErrnoException errnoException) {
            throw errnoException.rethrowAsSocketException();
        }
    }

}
