/*
 * Copyright (c) 2012, 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.
 *
 * 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.
 */

/* Test utility classes
 *
 */

import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class TestServers {

    private TestServers() { }

    /**
     * An abstract server identifies a server which listens on a port on on a
     * given machine.
     */
    static abstract class AbstractServer {

        private AbstractServer() {
        }

        public abstract int getPort();

        public abstract InetAddress getAddress();
    }

    /**
     * A downgraded type of AbstractServer which will refuse connections. Note:
     * use it once and throw it away - this implementation opens an anonymous
     * socket and closes it, returning the address of the closed socket. If
     * other servers are started afterwards, the address/port might get reused
     * and become connectable again - so it's not a good idea to assume that
     * connections using this address/port will always be refused. Connections
     * will be refused as long as the address/port of the refusing server has
     * not been reused.
     */
    static class RefusingServer extends AbstractServer {

        final InetAddress address;
        final int port;

        private RefusingServer(InetAddress address, int port) {
            this.address = address;
            this.port = port;
        }

        @Override
        public int getPort() {
            return port;
        }

        @Override
        public InetAddress getAddress() {
            return address;
        }

        public static RefusingServer startNewServer() throws IOException {
            ServerSocket socket = new ServerSocket(0, 100,
                    InetAddress.getLocalHost());
            RefusingServer server = new RefusingServer(socket.getInetAddress(),
                    socket.getLocalPort());
            socket.close();
            return server;
        }
    }

    /**
     * An abstract class for implementing small TCP servers for the nio tests
     * purposes. Disclaimer: This is a naive implementation that uses the old
     * networking APIs (not those from {@code java.nio.*}) and shamelessly
     * extends/creates Threads instead of using an executor service.
     */
    static abstract class AbstractTcpServer extends AbstractServer
            implements Runnable, Closeable {

        protected final long linger; // #of ms to wait before responding
        private Thread acceptThread; // thread waiting for accept
        // list of opened connections that should be closed on close.
        private List<TcpConnectionThread> connections = new ArrayList<>();
        private ServerSocket serverSocket; // the server socket
        private boolean started = false; // whether the server is started
        Throwable error = null;

        /**
         * Creates a new abstract TCP server.
         *
         * @param linger the amount of time the server should wait before
         * responding to requests.
         */
        protected AbstractTcpServer(long linger) {
            this.linger = linger;
        }

        /**
         * The local port to which the server is bound.
         *
         * @return The local port to which the server is bound.
         * @exception IllegalStateException is thrown if the server is not
         * started.
         */
        @Override
        public final synchronized int getPort() {
            if (!started) {
                throw new IllegalStateException("Not started");
            }
            return serverSocket.getLocalPort();
        }

        /**
         * The local address to which the server is bound.
         *
         * @return The local address to which the server is bound.
         * @exception IllegalStateException is thrown if the server is not
         * started.
         */
        @Override
        public final synchronized InetAddress getAddress() {
            if (!started) {
                throw new IllegalStateException("Not started");
            }
            return serverSocket.getInetAddress();
        }

        /**
         * Tells whether the server is started.
         *
         * @return true if the server is started.
         */
        public final synchronized boolean isStarted() {
            return started;
        }

        /**
         * Creates a new server socket.
         *
         * @param port local port to bind to.
         * @param backlog requested maximum length of the queue of incoming
         * connections.
         * @param address local address to bind to.
         * @return a new bound server socket ready to accept connections.
         * @throws IOException if the socket cannot be created or bound.
         */
        protected ServerSocket newServerSocket(int port, int backlog,
                InetAddress address)
                throws IOException {
            return new ServerSocket(port, backlog, address);
        }

        /**
         * Starts listening for connections.
         *
         * @throws IOException if the server socket cannot be created or bound.
         */
        public final synchronized void start() throws IOException {
            if (started) {
                return;
            }
            final ServerSocket socket =
                    newServerSocket(0, 100, InetAddress.getLocalHost());
            serverSocket = socket;
            acceptThread = new Thread(this);
            acceptThread.setDaemon(true);
            acceptThread.start();
            started = true;
        }

        /**
         * Calls {@code Thread.sleep(linger);}
         */
        protected final void lingerIfRequired() {
            if (linger > 0) {
                try {
                    Thread.sleep(linger);
                } catch (InterruptedException x) {
                    Thread.interrupted();
                    final ServerSocket socket = serverSocket();
                    if (socket != null && !socket.isClosed()) {
                        System.err.println("Thread interrupted...");
                    }
                }
            }
        }

        final synchronized ServerSocket serverSocket() {
            return this.serverSocket;
        }

        /**
         * The main accept loop.
         */
        @Override
        public final void run() {
            final ServerSocket sSocket = serverSocket();
            try {
                Socket s;
                while (isStarted() && !Thread.interrupted()
                        && (s = sSocket.accept()) != null) {
                    lingerIfRequired();
                    listen(s);
                }
            } catch (Exception x) {
                error = x;
            } finally {
                synchronized (this) {
                    if (!sSocket.isClosed()) {
                        try {
                            sSocket.close();
                        } catch (IOException x) {
                            System.err.println("Failed to close server socket");
                        }
                    }
                    if (started && this.serverSocket == sSocket) {
                        started = false;
                        this.serverSocket = null;
                        this.acceptThread = null;
                    }
                }
            }
        }

        /**
         * Represents a connection accepted by the server.
         */
        protected abstract class TcpConnectionThread extends Thread {

            protected final Socket socket;

            protected TcpConnectionThread(Socket socket) {
                this.socket = socket;
                this.setDaemon(true);
            }

            public void close() throws IOException {
                socket.close();
                interrupt();
            }
        }

        /**
         * Creates a new TcpConnnectionThread to handle the connection through
         * an accepted socket.
         *
         * @param s the socket returned by {@code serverSocket.accept()}.
         * @return a new TcpConnnectionThread to handle the connection through
         * an accepted socket.
         */
        protected abstract TcpConnectionThread createConnection(Socket s);

        /**
         * Creates and starts a new TcpConnectionThread to handle the accepted
         * socket.
         *
         * @param s the socket returned by {@code serverSocket.accept()}.
         */
        private synchronized void listen(Socket s) {
            TcpConnectionThread c = createConnection(s);
            c.start();
            addConnection(c);
        }

        /**
         * Add the connection to the list of accepted connections.
         *
         * @param connection an accepted connection.
         */
        protected synchronized void addConnection(
                TcpConnectionThread connection) {
            connections.add(connection);
        }

        /**
         * Remove the connection from the list of accepted connections.
         *
         * @param connection an accepted connection.
         */
        protected synchronized void removeConnection(
                TcpConnectionThread connection) {
            connections.remove(connection);
        }

        /**
         * Close the server socket and all the connections present in the list
         * of accepted connections.
         *
         * @throws IOException
         */
        @Override
        public synchronized void close() throws IOException {
            if (serverSocket != null && !serverSocket.isClosed()) {
                serverSocket.close();
            }
            if (acceptThread != null) {
                acceptThread.interrupt();
            }
            int failed = 0;
            for (TcpConnectionThread c : connections) {
                try {
                    c.close();
                } catch (IOException x) {
                    // no matter - we're closing.
                    failed++;
                }
            }
            connections.clear();
            if (failed > 0) {
                throw new IOException("Failed to close some connections");
            }
        }
    }

    /**
     * A small TCP Server that emulates the echo service for tests purposes. See
     * http://en.wikipedia.org/wiki/Echo_Protocol This server uses an anonymous
     * port - NOT the standard port 7. We don't guarantee that its behavior
     * exactly matches the RFC - the only purpose of this server is to have
     * something that responds to nio tests...
     */
    static final class EchoServer extends AbstractTcpServer {

        public EchoServer() {
            this(0L);
        }

        public EchoServer(long linger) {
            super(linger);
        }

        @Override
        protected TcpConnectionThread createConnection(Socket s) {
            return new EchoConnection(s);
        }

        private final class EchoConnection extends TcpConnectionThread {

            public EchoConnection(Socket socket) {
                super(socket);
            }

            @Override
            public void run() {
                try {
                    final InputStream is = socket.getInputStream();
                    final OutputStream out = socket.getOutputStream();
                    byte[] b = new byte[255];
                    int n;
                    while ((n = is.read(b)) > 0) {
                        lingerIfRequired();
                        out.write(b, 0, n);
                    }
                } catch (IOException io) {
                    // fall through to finally
                } finally {
                    if (!socket.isClosed()) {
                        try {
                            socket.close();
                        } catch (IOException x) {
                            System.err.println(
                                    "Failed to close echo connection socket");
                        }
                    }
                    removeConnection(this);
                }
            }
        }

        public static EchoServer startNewServer() throws IOException {
            return startNewServer(0);
        }

        public static EchoServer startNewServer(long linger) throws IOException {
            final EchoServer echoServer = new EchoServer(linger);
            echoServer.start();
            return echoServer;
        }
    }

    /**
     * A small TCP server that emulates the Day & Time service for tests
     * purposes. See http://en.wikipedia.org/wiki/Daytime_Protocol This server
     * uses an anonymous port - NOT the standard port 13. We don't guarantee
     * that its behavior exactly matches the RFC - the only purpose of this
     * server is to have something that responds to nio tests...
     */
    static final class DayTimeServer extends AbstractTcpServer {

        public DayTimeServer() {
            this(0L);
        }

        public DayTimeServer(long linger) {
            super(linger);
        }

        @Override
        protected TcpConnectionThread createConnection(Socket s) {
            return new DayTimeServerConnection(s);
        }

        @Override
        protected void addConnection(TcpConnectionThread connection) {
            // do nothing - the connection just write the date and terminates.
        }

        @Override
        protected void removeConnection(TcpConnectionThread connection) {
            // do nothing - we're not adding connections to the list...
        }

        private final class DayTimeServerConnection extends TcpConnectionThread {

            public DayTimeServerConnection(Socket socket) {
                super(socket);
            }

            @Override
            public void run() {
                try {
                    final OutputStream out = socket.getOutputStream();
                    lingerIfRequired();
                    out.write(new Date(System.currentTimeMillis())
                            .toString().getBytes("US-ASCII"));
                    out.flush();
                } catch (IOException io) {
                    // fall through to finally
                } finally {
                    if (!socket.isClosed()) {
                        try {
                            socket.close();
                        } catch (IOException x) {
                            System.err.println(
                                    "Failed to close echo connection socket");
                        }
                    }
                }
            }
        }

        public static DayTimeServer startNewServer()
                throws IOException {
            return startNewServer(0);
        }

        public static DayTimeServer startNewServer(long linger)
                throws IOException {
            final DayTimeServer daytimeServer = new DayTimeServer(linger);
            daytimeServer.start();
            return daytimeServer;
        }
    }

    /**
     * An abstract class for implementing small UDP Servers for the nio tests
     * purposes. Disclaimer: This is a naive implementation that uses the old
     * networking APIs (not those from {@code java.nio.*}) and shamelessly
     * extends/creates Threads instead of using an executor service.
     */
    static abstract class AbstractUdpServer extends AbstractServer
            implements Runnable, Closeable {

        protected final long linger; // #of ms to wait before responding
        private Thread acceptThread; // thread waiting for packets
        private DatagramSocket serverSocket; // the server socket
        private boolean started = false; // whether the server is started
        Throwable error = null;

        /**
         * Creates a new abstract UDP server.
         *
         * @param linger the amount of time the server should wait before
         * responding to requests.
         */
        protected AbstractUdpServer(long linger) {
            this.linger = linger;
        }

        /**
         * The local port to which the server is bound.
         *
         * @return The local port to which the server is bound.
         * @exception IllegalStateException is thrown if the server is not
         * started.
         */
        @Override
        public final synchronized int getPort() {
            if (!started) {
                throw new IllegalStateException("Not started");
            }
            return serverSocket.getLocalPort();
        }

        /**
         * The local address to which the server is bound.
         *
         * @return The local address to which the server is bound.
         * @exception IllegalStateException is thrown if the server is not
         * started.
         */
        @Override
        public final synchronized InetAddress getAddress() {
            if (!started) {
                throw new IllegalStateException("Not started");
            }
            return serverSocket.getLocalAddress();
        }

        /**
         * Tells whether the server is started.
         *
         * @return true if the server is started.
         */
        public final synchronized boolean isStarted() {
            return started;
        }

        /**
         * Creates a new datagram socket.
         *
         * @param port local port to bind to.
         * @param address local address to bind to.
         * @return a new bound server socket ready to listen for packets.
         * @throws IOException if the socket cannot be created or bound.
         */
        protected DatagramSocket newDatagramSocket(int port,
                InetAddress address)
                throws IOException {
            return new DatagramSocket(port, address);
        }

        /**
         * Starts listening for connections.
         *
         * @throws IOException if the server socket cannot be created or bound.
         */
        public final synchronized void start() throws IOException {
            if (started) {
                return;
            }
            final DatagramSocket socket =
                    newDatagramSocket(0, InetAddress.getLocalHost());
            serverSocket = socket;
            acceptThread = new Thread(this);
            acceptThread.setDaemon(true);
            acceptThread.start();
            started = true;
        }

        /**
         * Calls {@code Thread.sleep(linger);}
         */
        protected final void lingerIfRequired() {
            if (linger > 0) {
                try {
                    Thread.sleep(linger);
                } catch (InterruptedException x) {
                    Thread.interrupted();
                    final DatagramSocket socket = serverSocket();
                    if (socket != null && !socket.isClosed()) {
                        System.err.println("Thread interrupted...");
                    }
                }
            }
        }

        final synchronized DatagramSocket serverSocket() {
            return this.serverSocket;
        }

        final synchronized boolean send(DatagramSocket socket,
                DatagramPacket response) throws IOException {
            if (!socket.isClosed()) {
                socket.send(response);
                return true;
            } else {
                return false;
            }
        }

        /**
         * The main receive loop.
         */
        @Override
        public final void run() {
            final DatagramSocket sSocket = serverSocket();
            try {
                final int size = Math.max(1024, sSocket.getReceiveBufferSize());
                if (size > sSocket.getReceiveBufferSize()) {
                    sSocket.setReceiveBufferSize(size);
                }
                while (isStarted() && !Thread.interrupted() && !sSocket.isClosed()) {
                    final byte[] buf = new byte[size];
                    final DatagramPacket packet =
                            new DatagramPacket(buf, buf.length);
                    lingerIfRequired();
                    sSocket.receive(packet);
                    //System.out.println("Received packet from: "
                    //        + packet.getAddress()+":"+packet.getPort());
                    handle(sSocket, packet);
                }
            } catch (Exception x) {
                error = x;
            } finally {
                synchronized (this) {
                    if (!sSocket.isClosed()) {
                        sSocket.close();
                    }
                    if (started && this.serverSocket == sSocket) {
                        started = false;
                        this.serverSocket = null;
                        this.acceptThread = null;
                    }
                }
            }
        }

        /**
         * Represents an UDP request received by the server.
         */
        protected abstract class UdpRequestThread extends Thread {

            protected final DatagramPacket request;
            protected final DatagramSocket socket;

            protected UdpRequestThread(DatagramSocket socket, DatagramPacket request) {
                this.socket = socket;
                this.request = request;
                this.setDaemon(true);
            }
        }

        /**
         * Creates a new UdpRequestThread to handle a DatagramPacket received
         * through a DatagramSocket.
         *
         * @param socket the socket through which the request was received.
         * @param request the datagram packet received through the socket.
         * @return a new UdpRequestThread to handle the request received through
         * a DatagramSocket.
         */
        protected abstract UdpRequestThread createConnection(DatagramSocket socket,
                DatagramPacket request);

        /**
         * Creates and starts a new UdpRequestThread to handle the received
         * datagram packet.
         *
         * @param socket the socket through which the request was received.
         * @param request the datagram packet received through the socket.
         */
        private synchronized void handle(DatagramSocket socket,
                DatagramPacket request) {
            UdpRequestThread c = createConnection(socket, request);
            // c can be null if the request requires no response.
            if (c != null) {
                c.start();
            }
        }

        /**
         * Close the server socket.
         *
         * @throws IOException
         */
        @Override
        public synchronized void close() throws IOException {
            if (serverSocket != null && !serverSocket.isClosed()) {
                serverSocket.close();
            }
            if (acceptThread != null) {
                acceptThread.interrupt();
            }
        }
    }

    /**
     * A small UDP Server that emulates the discard service for tests purposes.
     * See http://en.wikipedia.org/wiki/Discard_Protocol This server uses an
     * anonymous port - NOT the standard port 9. We don't guarantee that its
     * behavior exactly matches the RFC - the only purpose of this server is to
     * have something that responds to nio tests...
     */
    static final class UdpDiscardServer extends AbstractUdpServer {

        public UdpDiscardServer() {
            this(0L);
        }

        public UdpDiscardServer(long linger) {
            super(linger);
        }

        @Override
        protected UdpRequestThread createConnection(DatagramSocket socket,
                DatagramPacket request) {
            // no response required
            return null;
        }

        public static UdpDiscardServer startNewServer() throws IOException {
            return startNewServer(0);
        }

        public static UdpDiscardServer startNewServer(long linger) throws IOException {
            final UdpDiscardServer discardServer = new UdpDiscardServer(linger);
            discardServer.start();
            return discardServer;
        }
    }

    /**
     * A small UDP Server that emulates the echo service for tests purposes. See
     * http://en.wikipedia.org/wiki/Echo_Protocol This server uses an anonymous
     * port - NOT the standard port 7. We don't guarantee that its behavior
     * exactly matches the RFC - the only purpose of this server is to have
     * something that responds to nio tests...
     */
    static final class UdpEchoServer extends AbstractUdpServer {

        public UdpEchoServer() {
            this(0L);
        }

        public UdpEchoServer(long linger) {
            super(linger);
        }

        @Override
        protected UdpEchoRequest createConnection(DatagramSocket socket,
                DatagramPacket request) {
            return new UdpEchoRequest(socket, request);
        }

        private final class UdpEchoRequest extends UdpRequestThread {

            public UdpEchoRequest(DatagramSocket socket, DatagramPacket request) {
                super(socket, request);
            }

            @Override
            public void run() {
                try {
                    lingerIfRequired();
                    final DatagramPacket response =
                            new DatagramPacket(request.getData(),
                                    request.getOffset(), request.getLength(),
                                    request.getAddress(), request.getPort());
                    send(socket, response);
                } catch (IOException io) {
                    System.err.println("Failed to send response: " + io);
                    io.printStackTrace(System.err);
                }
            }
        }

        public static UdpEchoServer startNewServer() throws IOException {
            return startNewServer(0);
        }

        public static UdpEchoServer startNewServer(long linger) throws IOException {
            final UdpEchoServer echoServer = new UdpEchoServer(linger);
            echoServer.start();
            return echoServer;
        }
    }

    /**
     * A small UDP server that emulates the Day & Time service for tests
     * purposes. See http://en.wikipedia.org/wiki/Daytime_Protocol This server
     * uses an anonymous port - NOT the standard port 13. We don't guarantee
     * that its behavior exactly matches the RFC - the only purpose of this
     * server is to have something that responds to nio tests...
     */
    static final class UdpDayTimeServer extends AbstractUdpServer {

        public UdpDayTimeServer() {
            this(0L);
        }

        public UdpDayTimeServer(long linger) {
            super(linger);
        }

        @Override
        protected UdpDayTimeRequestThread createConnection(DatagramSocket socket,
                DatagramPacket request) {
            return new UdpDayTimeRequestThread(socket, request);
        }

        private final class UdpDayTimeRequestThread extends UdpRequestThread {

            public UdpDayTimeRequestThread(DatagramSocket socket,
                    DatagramPacket request) {
                super(socket, request);
            }

            @Override
            public void run() {
                try {
                    lingerIfRequired();
                    final byte[] data = new Date(System.currentTimeMillis())
                            .toString().getBytes("US-ASCII");
                    final DatagramPacket response =
                            new DatagramPacket(data, 0, data.length,
                                    request.getAddress(), request.getPort());
                    send(socket, response);
                } catch (IOException io) {
                    System.err.println("Failed to send response: " + io);
                    io.printStackTrace(System.err);
                }
            }
        }

        public static UdpDayTimeServer startNewServer() throws IOException {
            return startNewServer(0);
        }

        public static UdpDayTimeServer startNewServer(long linger)
                throws IOException {
            final UdpDayTimeServer echoServer = new UdpDayTimeServer(linger);
            echoServer.start();
            return echoServer;
        }
    }
}
