/*
 * Copyright (c) 2005, 2006, 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 sun.net.httpserver;

import java.net.*;
import java.nio.*;
import java.io.*;
import java.nio.channels.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import javax.net.ssl.*;
import javax.net.ssl.SSLEngineResult.*;
import com.sun.net.httpserver.*;
import com.sun.net.httpserver.spi.*;

/**
 * given a non-blocking SocketChannel, it produces
 * (blocking) streams which encrypt/decrypt the SSL content
 * and handle the SSL handshaking automatically.
 */

class SSLStreams {

    SSLContext sslctx;
    SocketChannel chan;
    TimeSource time;
    ServerImpl server;
    SSLEngine engine;
    EngineWrapper wrapper;
    OutputStream os;
    InputStream is;
    static long readTimeout = ServerConfig.getReadTimeout();
    static long writeTimeout = ServerConfig.getWriteTimeout();

    /* held by thread doing the hand-shake on this connection */
    Lock handshaking = new ReentrantLock();

    SSLStreams (ServerImpl server, SSLContext sslctx, SocketChannel chan) throws IOException {
        this.server = server;
        this.time= (TimeSource)server;
        this.sslctx= sslctx;
        this.chan= chan;
        InetSocketAddress addr =
                (InetSocketAddress)chan.socket().getRemoteSocketAddress();
        engine = sslctx.createSSLEngine (addr.getHostName(), addr.getPort());
        engine.setUseClientMode (false);
        HttpsConfigurator cfg = server.getHttpsConfigurator();
        configureEngine (cfg, addr);
        wrapper = new EngineWrapper (chan, engine);
    }

    private void configureEngine(HttpsConfigurator cfg, InetSocketAddress addr){
        if (cfg != null) {
            Parameters params = new Parameters (cfg, addr);
            cfg.configure (params);
            SSLParameters sslParams = params.getSSLParameters();
            if (sslParams != null) {
                engine.setSSLParameters (sslParams);
            } else {
                /* tiger compatibility */
                if (params.getCipherSuites() != null) {
                    try {
                        engine.setEnabledCipherSuites (
                            params.getCipherSuites()
                        );
                    } catch (IllegalArgumentException e) { /* LOG */}
                }
                engine.setNeedClientAuth (params.getNeedClientAuth());
                engine.setWantClientAuth (params.getWantClientAuth());
                if (params.getProtocols() != null) {
                    try {
                        engine.setEnabledProtocols (
                            params.getProtocols()
                        );
                    } catch (IllegalArgumentException e) { /* LOG */}
                }
            }
        }
    }

    class Parameters extends HttpsParameters {
        InetSocketAddress addr;
        SSLParameters params;
        HttpsConfigurator cfg;

        Parameters (HttpsConfigurator cfg, InetSocketAddress addr) {
            this.addr = addr;
            this.cfg = cfg;
        }
        public InetSocketAddress getClientAddress () {
            return addr;
        }
        public HttpsConfigurator getHttpsConfigurator() {
            return cfg;
        }
        public void setSSLParameters (SSLParameters p) {
            params = p;
        }
        SSLParameters getSSLParameters () {
            return params;
        }
    }

    /**
     * cleanup resources allocated inside this object
     */
    void close () throws IOException {
        wrapper.close();
    }

    /**
     * return the SSL InputStream
     */
    InputStream getInputStream () throws IOException {
        if (is == null) {
            is = new InputStream();
        }
        return is;
    }

    /**
     * return the SSL OutputStream
     */
    OutputStream getOutputStream () throws IOException {
        if (os == null) {
            os = new OutputStream();
        }
        return os;
    }

    SSLEngine getSSLEngine () {
        return engine;
    }

    /**
     * request the engine to repeat the handshake on this session
     * the handshake must be driven by reads/writes on the streams
     * Normally, not necessary to call this.
     */
    void beginHandshake() throws SSLException {
        engine.beginHandshake();
    }

    class WrapperResult {
        SSLEngineResult result;

        /* if passed in buffer was not big enough then the
         * a reallocated buffer is returned here
         */
        ByteBuffer buf;
    }

    int app_buf_size;
    int packet_buf_size;

    enum BufType {
        PACKET, APPLICATION
    };

    private ByteBuffer allocate (BufType type) {
        return allocate (type, -1);
    }

    private ByteBuffer allocate (BufType type, int len) {
        assert engine != null;
        synchronized (this) {
            int size;
            if (type == BufType.PACKET) {
                if (packet_buf_size == 0) {
                    SSLSession sess = engine.getSession();
                    packet_buf_size = sess.getPacketBufferSize();
                }
                if (len > packet_buf_size) {
                    packet_buf_size = len;
                }
                size = packet_buf_size;
            } else {
                if (app_buf_size == 0) {
                    SSLSession sess = engine.getSession();
                    app_buf_size = sess.getApplicationBufferSize();
                }
                if (len > app_buf_size) {
                    app_buf_size = len;
                }
                size = app_buf_size;
            }
            return ByteBuffer.allocate (size);
        }
    }

    /* reallocates the buffer by :-
     * 1. creating a new buffer double the size of the old one
     * 2. putting the contents of the old buffer into the new one
     * 3. set xx_buf_size to the new size if it was smaller than new size
     *
     * flip is set to true if the old buffer needs to be flipped
     * before it is copied.
     */
    private ByteBuffer realloc (ByteBuffer b, boolean flip, BufType type) {
        synchronized (this) {
            int nsize = 2 * b.capacity();
            ByteBuffer n = allocate (type, nsize);
            if (flip) {
                b.flip();
            }
            n.put(b);
            b = n;
        }
        return b;
    }
    /**
     * This is a thin wrapper over SSLEngine and the SocketChannel,
     * which guarantees the ordering of wraps/unwraps with respect to the underlying
     * channel read/writes. It handles the UNDER/OVERFLOW status codes
     * It does not handle the handshaking status codes, or the CLOSED status code
     * though once the engine is closed, any attempt to read/write to it
     * will get an exception.  The overall result is returned.
     * It functions synchronously/blocking
     */
    class EngineWrapper {

        SocketChannel chan;
        SSLEngine engine;
        SelectorCache sc;
        Selector write_selector, read_selector;
        SelectionKey wkey, rkey;
        Object wrapLock, unwrapLock;
        ByteBuffer unwrap_src, wrap_dst;
        boolean closed = false;
        int u_remaining; // the number of bytes left in unwrap_src after an unwrap()

        EngineWrapper (SocketChannel chan, SSLEngine engine) throws IOException {
            this.chan = chan;
            this.engine = engine;
            wrapLock = new Object();
            unwrapLock = new Object();
            unwrap_src = allocate(BufType.PACKET);
            wrap_dst = allocate(BufType.PACKET);
            sc = SelectorCache.getSelectorCache();
            write_selector = sc.getSelector();
            wkey = chan.register (write_selector, SelectionKey.OP_WRITE);
            read_selector = sc.getSelector();
            wkey = chan.register (read_selector, SelectionKey.OP_READ);
        }

        void close () throws IOException {
            sc.freeSelector (write_selector);
            sc.freeSelector (read_selector);
        }

        /* try to wrap and send the data in src. Handles OVERFLOW.
         * Might block if there is an outbound blockage or if another
         * thread is calling wrap(). Also, might not send any data
         * if an unwrap is needed.
         */
        WrapperResult wrapAndSend(ByteBuffer src) throws IOException {
            return wrapAndSendX(src, false);
        }

        WrapperResult wrapAndSendX(ByteBuffer src, boolean ignoreClose) throws IOException {
            if (closed && !ignoreClose) {
                throw new IOException ("Engine is closed");
            }
            Status status;
            WrapperResult r = new WrapperResult();
            synchronized (wrapLock) {
                wrap_dst.clear();
                do {
                    r.result = engine.wrap (src, wrap_dst);
                    status = r.result.getStatus();
                    if (status == Status.BUFFER_OVERFLOW) {
                        wrap_dst = realloc (wrap_dst, true, BufType.PACKET);
                    }
                } while (status == Status.BUFFER_OVERFLOW);
                if (status == Status.CLOSED && !ignoreClose) {
                    closed = true;
                    return r;
                }
                if (r.result.bytesProduced() > 0) {
                    wrap_dst.flip();
                    int l = wrap_dst.remaining();
                    assert l == r.result.bytesProduced();
                    long currtime = time.getTime();
                    long maxtime = currtime + writeTimeout;
                    while (l>0) {
                        write_selector.select(writeTimeout); // timeout
                        currtime = time.getTime();
                        if (currtime > maxtime) {
                            throw new SocketTimeoutException ("write timed out");
                        }
                        write_selector.selectedKeys().clear();
                        l -= chan.write (wrap_dst);
                    }
                }
            }
            return r;
        }

        /* block until a complete message is available and return it
         * in dst, together with the Result. dst may have been re-allocated
         * so caller should check the returned value in Result
         * If handshaking is in progress then, possibly no data is returned
         */
        WrapperResult recvAndUnwrap(ByteBuffer dst) throws IOException {
            Status status = Status.OK;
            WrapperResult r = new WrapperResult();
            r.buf = dst;
            if (closed) {
                throw new IOException ("Engine is closed");
            }
            boolean needData;
            if (u_remaining > 0) {
                unwrap_src.compact();
                unwrap_src.flip();
                needData = false;
            } else {
                unwrap_src.clear();
                needData = true;
            }
            synchronized (unwrapLock) {
                int x,y;
                do {
                    if (needData) {
                        long currTime = time.getTime();
                        long maxtime = currTime + readTimeout;
                        do {
                            if (currTime > maxtime) {
                                throw new SocketTimeoutException ("read timedout");
                            }
                            y = read_selector.select (readTimeout);
                            currTime = time.getTime();
                        } while (y != 1);
                        read_selector.selectedKeys().clear();
                        x = chan.read (unwrap_src);
                        if (x == -1) {
                            throw new IOException ("connection closed for reading");
                        }
                        unwrap_src.flip();
                    }
                    r.result = engine.unwrap (unwrap_src, r.buf);
                    status = r.result.getStatus();
                    if (status == Status.BUFFER_UNDERFLOW) {
                        if (unwrap_src.limit() == unwrap_src.capacity()) {
                            /* buffer not big enough */
                            unwrap_src = realloc (
                                unwrap_src, false, BufType.PACKET
                            );
                        } else {
                            /* Buffer not full, just need to read more
                             * data off the channel. Reset pointers
                             * for reading off SocketChannel
                             */
                            unwrap_src.position (unwrap_src.limit());
                            unwrap_src.limit (unwrap_src.capacity());
                        }
                        needData = true;
                    } else if (status == Status.BUFFER_OVERFLOW) {
                        r.buf = realloc (r.buf, true, BufType.APPLICATION);
                        needData = false;
                    } else if (status == Status.CLOSED) {
                        closed = true;
                        r.buf.flip();
                        return r;
                    }
                } while (status != Status.OK);
            }
            u_remaining = unwrap_src.remaining();
            return r;
        }
    }

    /**
     * send the data in the given ByteBuffer. If a handshake is needed
     * then this is handled within this method. When this call returns,
     * all of the given user data has been sent and any handshake has been
     * completed. Caller should check if engine has been closed.
     */
    public WrapperResult sendData (ByteBuffer src) throws IOException {
        WrapperResult r=null;
        while (src.remaining() > 0) {
            r = wrapper.wrapAndSend(src);
            Status status = r.result.getStatus();
            if (status == Status.CLOSED) {
                doClosure ();
                return r;
            }
            HandshakeStatus hs_status = r.result.getHandshakeStatus();
            if (hs_status != HandshakeStatus.FINISHED &&
                hs_status != HandshakeStatus.NOT_HANDSHAKING)
            {
                doHandshake(hs_status);
            }
        }
        return r;
    }

    /**
     * read data thru the engine into the given ByteBuffer. If the
     * given buffer was not large enough, a new one is allocated
     * and returned. This call handles handshaking automatically.
     * Caller should check if engine has been closed.
     */
    public WrapperResult recvData (ByteBuffer dst) throws IOException {
        /* we wait until some user data arrives */
        WrapperResult r = null;
        assert dst.position() == 0;
        while (dst.position() == 0) {
            r = wrapper.recvAndUnwrap (dst);
            dst = (r.buf != dst) ? r.buf: dst;
            Status status = r.result.getStatus();
            if (status == Status.CLOSED) {
                doClosure ();
                return r;
            }

            HandshakeStatus hs_status = r.result.getHandshakeStatus();
            if (hs_status != HandshakeStatus.FINISHED &&
                hs_status != HandshakeStatus.NOT_HANDSHAKING)
            {
                doHandshake (hs_status);
            }
        }
        dst.flip();
        return r;
    }

    /* we've received a close notify. Need to call wrap to send
     * the response
     */
    void doClosure () throws IOException {
        try {
            handshaking.lock();
            ByteBuffer tmp = allocate(BufType.APPLICATION);
            WrapperResult r;
            do {
                tmp.clear();
                tmp.flip ();
                r = wrapper.wrapAndSendX (tmp, true);
            } while (r.result.getStatus() != Status.CLOSED);
        } finally {
            handshaking.unlock();
        }
    }

    /* do the (complete) handshake after acquiring the handshake lock.
     * If two threads call this at the same time, then we depend
     * on the wrapper methods being idempotent. eg. if wrapAndSend()
     * is called with no data to send then there must be no problem
     */
    void doHandshake (HandshakeStatus hs_status) throws IOException {
        try {
            handshaking.lock();
            ByteBuffer tmp = allocate(BufType.APPLICATION);
            while (hs_status != HandshakeStatus.FINISHED &&
                   hs_status != HandshakeStatus.NOT_HANDSHAKING)
            {
                WrapperResult r = null;
                switch (hs_status) {
                    case NEED_TASK:
                        Runnable task;
                        while ((task = engine.getDelegatedTask()) != null) {
                            /* run in current thread, because we are already
                             * running an external Executor
                             */
                            task.run();
                        }
                        /* fall thru - call wrap again */
                    case NEED_WRAP:
                        tmp.clear();
                        tmp.flip();
                        r = wrapper.wrapAndSend(tmp);
                        break;

                    case NEED_UNWRAP:
                        tmp.clear();
                        r = wrapper.recvAndUnwrap (tmp);
                        if (r.buf != tmp) {
                            tmp = r.buf;
                        }
                        assert tmp.position() == 0;
                        break;
                }
                hs_status = r.result.getHandshakeStatus();
            }
        } finally {
            handshaking.unlock();
        }
    }

    /**
     * represents an SSL input stream. Multiple https requests can
     * be sent over one stream. closing this stream causes an SSL close
     * input.
     */
    class InputStream extends java.io.InputStream {

        ByteBuffer bbuf;
        boolean closed = false;

        /* this stream eof */
        boolean eof = false;

        boolean needData = true;

        InputStream () {
            bbuf = allocate (BufType.APPLICATION);
        }

        public int read (byte[] buf, int off, int len) throws IOException {
            if (closed) {
                throw new IOException ("SSL stream is closed");
            }
            if (eof) {
                return 0;
            }
            int available=0;
            if (!needData) {
                available = bbuf.remaining();
                needData = (available==0);
            }
            if (needData) {
                bbuf.clear();
                WrapperResult r = recvData (bbuf);
                bbuf = r.buf== bbuf? bbuf: r.buf;
                if ((available=bbuf.remaining()) == 0) {
                    eof = true;
                    return 0;
                } else {
                    needData = false;
                }
            }
            /* copy as much as possible from buf into users buf */
            if (len > available) {
                len = available;
            }
            bbuf.get (buf, off, len);
            return len;
        }

        public int available () throws IOException {
            return bbuf.remaining();
        }

        public boolean markSupported () {
            return false; /* not possible with SSLEngine */
        }

        public void reset () throws IOException {
            throw new IOException ("mark/reset not supported");
        }

        public long skip (long s) throws IOException {
            int n = (int)s;
            if (closed) {
                throw new IOException ("SSL stream is closed");
            }
            if (eof) {
                return 0;
            }
            int ret = n;
            while (n > 0) {
                if (bbuf.remaining() >= n) {
                    bbuf.position (bbuf.position()+n);
                    return ret;
                } else {
                    n -= bbuf.remaining();
                    bbuf.clear();
                    WrapperResult r = recvData (bbuf);
                    bbuf = r.buf==bbuf? bbuf: r.buf;
                }
            }
            return ret; /* not reached */
        }

        /**
         * close the SSL connection. All data must have been consumed
         * before this is called. Otherwise an exception will be thrown.
         * [Note. May need to revisit this. not quite the normal close() symantics
         */
        public void close () throws IOException {
            eof = true;
            engine.closeInbound ();
        }

        public int read (byte[] buf) throws IOException {
            return read (buf, 0, buf.length);
        }

        byte single[] = new byte [1];

        public int read () throws IOException {
            int n = read (single, 0, 1);
            if (n == 0) {
                return -1;
            } else {
                return single[0] & 0xFF;
            }
        }
    }

    /**
     * represents an SSL output stream. plain text data written to this stream
     * is encrypted by the stream. Multiple HTTPS responses can be sent on
     * one stream. closing this stream initiates an SSL closure
     */
    class OutputStream extends java.io.OutputStream {
        ByteBuffer buf;
        boolean closed = false;
        byte single[] = new byte[1];

        OutputStream() {
            buf = allocate(BufType.APPLICATION);
        }

        public void write(int b) throws IOException {
            single[0] = (byte)b;
            write (single, 0, 1);
        }

        public void write(byte b[]) throws IOException {
            write (b, 0, b.length);
        }
        public void write(byte b[], int off, int len) throws IOException {
            if (closed) {
                throw new IOException ("output stream is closed");
            }
            while (len > 0) {
                int l = len > buf.capacity() ? buf.capacity() : len;
                buf.clear();
                buf.put (b, off, l);
                len -= l;
                off += l;
                buf.flip();
                WrapperResult r = sendData (buf);
                if (r.result.getStatus() == Status.CLOSED) {
                    closed = true;
                    if (len > 0) {
                        throw new IOException ("output stream is closed");
                    }
                }
            }
        }

        public void flush() throws IOException {
            /* no-op */
        }

        public void close() throws IOException {
            WrapperResult r=null;
            engine.closeOutbound();
            closed = true;
            HandshakeStatus stat = HandshakeStatus.NEED_WRAP;
            buf.clear();
            while (stat == HandshakeStatus.NEED_WRAP) {
                r = wrapper.wrapAndSend (buf);
                stat = r.result.getHandshakeStatus();
            }
            assert r.result.getStatus() == Status.CLOSED;
        }
    }
}
