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

//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//

/*
 * @test
 * @bug 8274736 8277970 8355262
 * @summary Concurrent read/close of SSLSockets causes SSLSessions to be
 *          invalidated unnecessarily
 * @library /javax/net/ssl/templates
 * @run main/othervm NoInvalidateSocketException TLSv1.3
 * @run main/othervm NoInvalidateSocketException TLSv1.2
 * @run main/othervm -Djdk.tls.client.enableSessionTicketExtension=false
 *      NoInvalidateSocketException TLSv1.2
 */



import java.io.*;
import javax.net.ssl.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

public class NoInvalidateSocketException extends SSLSocketTemplate {
    private static final int ITERATIONS = 10;

    // This controls how long the main thread waits before closing the socket.
    // This may need tweaking for different environments to get the timing
    // right.
    private static final int CLOSE_DELAY = 10;

    private static SSLContext clientSSLCtx;
    private static SSLSocket theSSLSocket;
    private static SSLSession theSSLSession;
    private static InputStream theInputStream;
    private static String theSSLSocketHashCode;
    private static SSLSession lastSSLSession;
    private static final List<SSLSocket> serverCleanupList = new ArrayList<>();
    private static String tlsVersion = null;

    private static int invalidSessCount = 0;
    private static volatile boolean readFromSocket = false;
    private static volatile boolean finished = false;

    public static void main(String[] args) throws Exception {
        if (System.getProperty("javax.net.debug") == null) {
            System.setProperty("javax.net.debug", "session");
        }

        if (args != null && args.length >= 1) {
            tlsVersion = args[0];
        }

        new NoInvalidateSocketException(true).run();
        if (invalidSessCount > 0) {
            throw new RuntimeException("One or more sessions were improperly " +
                    "invalidated.");
        }
    }

    public NoInvalidateSocketException(boolean sepSrvThread) {
        super(sepSrvThread);
    }

    @Override
    public boolean isCustomizedClientConnection() {
        return true;
    }

    @Override
    public void runClientApplication(int serverPort) {
        Thread.currentThread().setName("Main Client Thread");

        // Create the SSLContext we'll use for client sockets for the
        // duration of the test.
        try {
            clientSSLCtx = createClientSSLContext();
        } catch (Exception e) {
            throw new RuntimeException("Failed to create client ctx", e);
        }

        // Create the reader thread
        ReaderThread readerThread = new ReaderThread();
        readerThread.setName("Client Reader Thread");
        readerThread.start();

        try {
            for (int i = 0; i < ITERATIONS; i++) {
                openSSLSocket();
                doHandshake();
                getInputStream();
                getAndCompareSession();

                // Perform the Close/Read MT collision
                readCloseMultiThreaded();

                // Check to make sure that the initially negotiated session
                // remains intact.
                isSessionValid();

                lastSSLSession = theSSLSession;

                // Insert a short gap between iterations
                Thread.sleep(1000);
                System.out.println();
            }
        } catch (Exception e) {
            logToConsole("Unexpected Exception: " + e);
        } finally {
            // Tell the reader thread to finish
            finished = true;
        }
    }

    private void readCloseMultiThreaded() throws IOException,
            InterruptedException {
        // Tell the reader thread to start trying to read from this
        // socket
        readFromSocket = true;

        // Short pause to give the reader thread time to start
        // reading.
        if (CLOSE_DELAY > 0) {
            Thread.sleep(CLOSE_DELAY);
        }

        // The problem happens when the reader thread tries to read
        // from the socket while this thread is in the close() call
        closeSSLSocket();

        // Pause to give the reader thread time to discover that the
        // socket is closed and throw a SocketException
        Thread.sleep(500);
    }

    private class ReaderThread extends Thread {
        public void run() {
            // This thread runs in a tight loop until
            // readFromSocket == true
            while (!finished) {
                if (readFromSocket) {
                    int result = 0;
                    try {
                        // If the timing is just
                        // right, this will throw a SocketException
                        // and the SSLSession will be
                        // invalidated.
                        result = readFromSSLSocket();
                    } catch (Exception e) {
                        logToConsole("Exception reading from SSLSocket@" +
                                theSSLSocketHashCode + ": " + e);
                        e.printStackTrace(System.out);

                        // Stop trying to read from
                        // the socket now
                        readFromSocket = false;
                    }

                    if (result == -1) {
                        logToConsole("Reached end of stream reading from " +
                                "SSLSocket@" + theSSLSocketHashCode);

                        // Stop trying to read from
                        // the socket now
                        readFromSocket = false;
                    }
                }
            }
        }
    }

    private void openSSLSocket() throws IOException {
        theSSLSocket = (SSLSocket)clientSSLCtx.getSocketFactory().
                createSocket(serverAddress, serverPort);
        if (tlsVersion != null) {
            theSSLSocket.setEnabledProtocols(new String[] { tlsVersion });
        }
        theSSLSocketHashCode = String.format("%08x", theSSLSocket.hashCode());
        logToConsole("Opened SSLSocket@" + theSSLSocketHashCode);
    }

    private void doHandshake() throws IOException {
        logToConsole("Started handshake on SSLSocket@" +
                theSSLSocketHashCode);
        theSSLSocket.startHandshake();
        logToConsole("Finished handshake on SSLSocket@" +
                theSSLSocketHashCode);
    }

    private void getInputStream() throws IOException {
        theInputStream = theSSLSocket.getInputStream();
    }

    private void getAndCompareSession() {
        theSSLSession = theSSLSocket.getSession();

        // Have we opened a new session or re-used the last one?
        if (lastSSLSession == null ||
                !theSSLSession.equals(lastSSLSession)) {
            logToConsole("*** OPENED NEW SESSION ***: " +
                    theSSLSession);
        } else {
            logToConsole("*** RE-USING PREVIOUS SESSION ***: " +
                    theSSLSession + ")");
        }
    }

    private void closeSSLSocket() throws IOException {
        logToConsole("Closing SSLSocket@" + theSSLSocketHashCode);
        theSSLSocket.close();
        logToConsole("Closed SSLSocket@" + theSSLSocketHashCode);
    }

    private int readFromSSLSocket() throws Exception {
        logToConsole("Started reading from SSLSocket@" +
                theSSLSocketHashCode);
        int result = theInputStream.read();
        logToConsole("Finished reading from SSLSocket@" +
                theSSLSocketHashCode + ": result = " + result);
        return result;
    }

    private void isSessionValid() {
        // Is the session still valid?
        if (theSSLSession.isValid()) {
            logToConsole("*** " + theSSLSession + " IS VALID ***");
        } else {
            logToConsole("*** " + theSSLSession + " IS INVALID ***");
            invalidSessCount++;
        }
    }

    private static void logToConsole(String s) {
        System.out.println(System.nanoTime() + ": " +
                Thread.currentThread().getName() + ": " + s);
    }

    @Override
    public void doServerSide() throws Exception {
        Thread.currentThread().setName("Server Listener Thread");
        SSLContext context = createServerSSLContext();
        SSLServerSocketFactory sslssf = context.getServerSocketFactory();
        InetAddress serverAddress = this.serverAddress;
        SSLServerSocket sslServerSocket = serverAddress == null ?
                (SSLServerSocket)sslssf.createServerSocket(serverPort)
                : (SSLServerSocket)sslssf.createServerSocket();
        if (serverAddress != null) {
            sslServerSocket.bind(new InetSocketAddress(serverAddress,
                    serverPort));
        }
        configureServerSocket(sslServerSocket);
        serverPort = sslServerSocket.getLocalPort();
        logToConsole("Listening on " + sslServerSocket.getLocalSocketAddress());

        // Signal the client, the server is ready to accept connection.
        serverCondition.countDown();

        // Try to accept a connection in 10 seconds.
        // We will do this in a loop until the client flips the
        // finished variable to true
        SSLSocket sslSocket;

        int timeoutCount = 0;
        try {
            do {
                try {
                    sslSocket = (SSLSocket) sslServerSocket.accept();
                    timeoutCount = 0;   // Reset the timeout counter;
                    logToConsole("Accepted connection from " +
                            sslSocket.getRemoteSocketAddress());

                    // Add the socket to the cleanup list so it can get
                    // closed at the end of the test
                    serverCleanupList.add(sslSocket);

                    boolean clientIsReady =
                            clientCondition.await(30L, TimeUnit.SECONDS);
                    if (clientIsReady) {
                        // Handle the connection in a new thread
                        ServerHandlerThread sht = null;
                        try {
                             sht = new ServerHandlerThread(sslSocket);
                             sht.start();
                        } finally {
                            if (sht != null) {
                                sht.join();
                            }
                        }
                    }
                } catch (SocketTimeoutException ste) {
                    timeoutCount++;
                    // If we are finished then we can return, otherwise
                    // check if we've timed out too many times (an exception
                    // case).  One way or the other we will exit eventually.
                    if (finished) {
                        return;
                    } else if (timeoutCount >= 3) {
                        logToConsole("Server accept timeout exceeded");
                        throw ste;
                    }
                }
            } while (!finished);
        } finally {
            sslServerSocket.close();
            // run through the server cleanup list and close those sockets
            // as well.
            for (SSLSocket sock : serverCleanupList) {
                try {
                    if (sock != null) {
                        sock.close();
                    }
                } catch (IOException ioe) {
                    // Swallow these close failures as the server itself
                    // is shutting down anyway.
                }
            }
        }
    }

    @Override
    public void configureServerSocket(SSLServerSocket socket) {
        try {
            socket.setReuseAddress(true);
            socket.setSoTimeout(10000);
        } catch (SocketException se) {
            // Rethrow as unchecked to satisfy the override signature
            throw new RuntimeException(se);
        }
    }

    @Override
    public void runServerApplication(SSLSocket sslSocket) {
        Thread.currentThread().setName("Server Reader Thread");
        SSLSocket sock = null;
        sock = sslSocket;
        try {
            BufferedReader is = new BufferedReader(
                    new InputStreamReader(sock.getInputStream()));
            PrintWriter os = new PrintWriter(new BufferedWriter(
                    new OutputStreamWriter(sock.getOutputStream())));

            // Only handle a single burst of data
            char[] buf = new char[1024];
            int dataRead = is.read(buf);
            logToConsole(String.format("Received: %d bytes of data\n",
                    dataRead));

            os.println("Received connection from client");
            os.flush();
        } catch (IOException ioe) {
            // Swallow these exceptions for this test
        }
    }

    private class ServerHandlerThread extends Thread {
        SSLSocket sock;
        ServerHandlerThread(SSLSocket socket) {
            this.sock = Objects.requireNonNull(socket, "Illegal null socket");
        }

        @Override
        public void run() {
            try {
                runServerApplication(sock);
            } catch (Exception exc) {
                // Wrap inside an unchecked exception to satisfy Runnable
                throw new RuntimeException(exc);
            }
        }

        void close() {
            try {
                sock.close();
            } catch (IOException e) {
                // swallow this exception
            }
        }
    }
}
