/*
 * Copyright (c) 2015, 2023, 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
 * @modules java.net.http
 *          java.logging
 *          jdk.httpserver
 * @library /test/lib
 * @build jdk.test.lib.net.SimpleSSLContext
 * @compile ../../../com/sun/net/httpserver/LogFilter.java
 * @compile ../../../com/sun/net/httpserver/EchoHandler.java
 * @compile ../../../com/sun/net/httpserver/FileServerHandler.java
 * @run main/othervm/timeout=80 -Dsun.net.httpserver.idleInterval=50000 ManyRequestsLegacy
 * @run main/othervm/timeout=80 -Dtest.insertDelay=true -Dsun.net.httpserver.idleInterval=50000 ManyRequestsLegacy
 * @run main/othervm/timeout=80 -Dtest.chunkSize=64 -Dsun.net.httpserver.idleInterval=50000 ManyRequestsLegacy
 * @run main/othervm/timeout=80 -Dtest.insertDelay=true -Dsun.net.httpserver.idleInterval=50000
 *                              -Dtest.chunkSize=64 ManyRequestsLegacy
 * @summary Send a large number of requests asynchronously using the legacy
 *          URL.openConnection(), to help sanitize results of the test
 *          ManyRequest.java.
 */

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.HostnameVerifier;

import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsParameters;
import com.sun.net.httpserver.HttpsServer;
import com.sun.net.httpserver.HttpExchange;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URI;
import java.net.URLConnection;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Version;
import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Formatter;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Random;
import java.util.logging.Logger;
import java.util.logging.Level;

import jdk.test.lib.Platform;
import jdk.test.lib.RandomFactory;
import jdk.test.lib.net.SimpleSSLContext;
import static java.net.Proxy.NO_PROXY;

public class ManyRequestsLegacy {

    static final int MAX_COUNT = 20;
    static final int MAX_LIMIT = 40;
    static final AtomicInteger COUNT = new AtomicInteger();
    static final AtomicInteger LIMIT = new AtomicInteger(MAX_LIMIT);
    static final Random RANDOM = RandomFactory.getRandom();


    public static void main(String[] args) throws Exception {
        Logger logger = Logger.getLogger("com.sun.net.httpserver");
        logger.setLevel(Level.ALL);
        logger.info("TEST");
        System.out.println("Sending " + REQUESTS
                         + " requests; delay=" + INSERT_DELAY
                         + ", chunks=" + CHUNK_SIZE
                         + ", XFixed=" + XFIXED);
        SSLContext ctx = new SimpleSSLContext().get();
        SSLContext.setDefault(ctx);
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
        InetSocketAddress addr = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
        HttpsServer server = HttpsServer.create(addr, 0);
        server.setHttpsConfigurator(new Configurator(ctx));

        LegacyHttpClient client = new LegacyHttpClient();

        try {
            test(server, client);
            System.out.println("OK");
        } finally {
            server.stop(0);
        }
    }

    //static final int REQUESTS = 1000;
    static final int REQUESTS = MAX_COUNT;
    static final boolean INSERT_DELAY = Boolean.getBoolean("test.insertDelay");
    static final int CHUNK_SIZE = Math.max(0,
           Integer.parseInt(System.getProperty("test.chunkSize", "0")));
    static final boolean XFIXED = Boolean.getBoolean("test.XFixed");

    static class LegacyHttpClient {
        static final class LegacyHttpResponse implements HttpResponse<byte[]> {
            final HttpRequest request;
            final byte[] response;
            final int statusCode;
            public LegacyHttpResponse(HttpRequest request, int statusCode, byte[] response) {
                this.request = request;
                this.statusCode = statusCode;
                this.response = response;
            }
            private <T> T error() {
                throw new UnsupportedOperationException("Not supported yet.");
            }
            @Override
            public int statusCode() { return statusCode;}
            @Override
            public HttpRequest request() {return request;}
            @Override
            public Optional<HttpResponse<byte[]>> previousResponse() {return Optional.empty();}
            @Override
            public HttpHeaders headers() { return error(); }
            @Override
            public byte[] body() {return response;}
            @Override
            public Optional<SSLSession> sslSession() {
                return Optional.empty(); // for now
            }
            @Override
            public URI uri() { return request.uri();}
            @Override
            public HttpClient.Version version() { return Version.HTTP_1_1;}
        }

        private void debugCompleted(String tag, long startNanos, HttpRequest req) {
            System.err.println(tag + " elapsed "
                    + (System.nanoTime() - startNanos)/1000_000L
                    + " millis for " + req.method()
                    + " to " + req.uri());
        }

        CompletableFuture<? extends HttpResponse<byte[]>> sendAsync(HttpRequest r, byte[] buf) {
            long start = System.nanoTime();
            try {
                CompletableFuture<LegacyHttpResponse> cf = new CompletableFuture<>();
                URLConnection urlc = r.uri().toURL().openConnection(NO_PROXY);
                HttpURLConnection httpc = (HttpURLConnection)urlc;
                httpc.setRequestMethod(r.method());
                for (String s : r.headers().map().keySet()) {
                    httpc.setRequestProperty(s, r.headers().allValues(s)
                        .stream().collect(Collectors.joining(",")));
                }
                httpc.setDoInput(true);
                if (buf != null) httpc.setDoOutput(true);
                Thread t = new Thread(() -> {
                    try {
                        if (buf != null) {
                            try (OutputStream os = httpc.getOutputStream()) {
                                os.write(buf);
                                os.flush();
                            }
                        }
                        LegacyHttpResponse response = new LegacyHttpResponse(r,
                                httpc.getResponseCode(),httpc.getInputStream().readAllBytes());
                        cf.complete(response);
                    } catch(Throwable x) {
                        cf.completeExceptionally(x);
                    }
                });
                t.start();
                return cf.whenComplete((b,x) -> debugCompleted("ClientImpl (async)", start, r));
            } catch(Throwable t) {
                debugCompleted("ClientImpl (async)", start, r);
                return CompletableFuture.failedFuture(t);
            }
        }
    }

    static class TestEchoHandler extends EchoHandler {
        final Random rand = RANDOM;
        @Override
        public void handle(HttpExchange e) throws IOException {
            System.out.println("Server: received " + e.getRequestURI());
            super.handle(e);
        }
        @Override
        protected void close(HttpExchange t, OutputStream os) throws IOException {
            if (INSERT_DELAY) {
                try { Thread.sleep(rand.nextInt(200)); }
                catch (InterruptedException e) {}
            }
            System.out.println("Server: close outbound: " + t.getRequestURI());
            os.close();
        }
        @Override
        protected void close(HttpExchange t, InputStream is) throws IOException {
            if (INSERT_DELAY) {
                try { Thread.sleep(rand.nextInt(200)); }
                catch (InterruptedException e) {}
            }
            System.out.println("Server: close inbound: " + t.getRequestURI());
            is.close();
        }
    }

    static String now(long start) {
        long elapsed = System.nanoTime() - start;
        long ms = elapsed / 1000_000L;
        long s = ms / 1000L;
        if (s == 0) return ms + "ms: ";
        return s + "s, " + (ms - s * 1000L) + "ms: ";
    }

    static String failure(Throwable t) {
        String s = "\n\t failed: " + t;
        for (t = t.getCause(); t != null ; t = t.getCause()) {
            s = s + "\n\t\t  Caused by: " + t;
        }
        return s;
    }

    static void test(HttpsServer server, LegacyHttpClient client) throws Exception {
        int port = server.getAddress().getPort();
        URI baseURI = new URI("https://localhost:" + port + "/foo/x");
        server.createContext("/foo", new TestEchoHandler());
        server.start();

        // This loop implements a retry mechanism to work around an issue
        // on some systems (observed on Windows 10) that seem to be trying to
        // throttle the number of connections that can be made concurrently by
        // rejecting connection attempts.
        // On the first iteration of this loop, we will attempt 20 concurrent
        // requests. If this fails with ConnectException, we will retry the
        // 20 requests, but limiting the concurrency to 10 (LIMIT <- 10).
        // If this fails again, the test will fail.
        boolean done = false;
        LOOP: do {
            RequestLimiter limiter = new RequestLimiter(LIMIT.get());
            Random rand = RANDOM;
            CompletableFuture<?>[] results = new CompletableFuture<?>[REQUESTS];
            Map<HttpRequest,byte[]> bodies = new ConcurrentHashMap<>();
            long start = System.nanoTime();

            for (int i = 0; i < REQUESTS; i++) {
                byte[] buf = new byte[(i + 1) * CHUNK_SIZE + i + 1];  // different size bodies
                rand.nextBytes(buf);
                URI uri = new URI(baseURI.toString() + String.valueOf(i + 1));
                HttpRequest r = HttpRequest.newBuilder(uri)
                        .header("XFixed", "true")
                        .POST(BodyPublishers.ofByteArray(buf))
                        .build();
                bodies.put(r, buf);

                results[i] =
                        limiter.whenOkToSend()
                                .thenCompose((v) -> {
                                    System.out.println("Client: sendAsync: " + r.uri());
                                    return client.sendAsync(r, buf);
                                })
                                .handle((resp, t) -> {
                                    limiter.requestComplete();
                                    CompletionStage<Pair<HttpResponse<byte[]>, byte[]>> res;
                                    String now = now(start);
                                    if (t == null) {
                                        if (resp.statusCode() != 200) {
                                            String s = "Expected 200, got: " + resp.statusCode();
                                            System.out.println(now + s + " from "
                                                    + resp.request().uri().getPath());
                                            res = completedWithIOException(s);
                                            return res;
                                        } else {
                                            int counter = COUNT.incrementAndGet();
                                            System.out.println(now + "Result (" + counter + ") from "
                                                    + resp.request().uri().getPath());
                                        }
                                        res = CompletableFuture.completedStage(resp.body())
                                                .thenApply((b) -> new Pair<>(resp, b));
                                        return res;
                                    } else {
                                        int counter = COUNT.incrementAndGet();
                                        System.out.println(now + "Result (" + counter + ") from "
                                                + r.uri().getPath()
                                                + failure(t));
                                        res = CompletableFuture.failedFuture(t);
                                        return res;
                                    }
                                })
                                .thenCompose(c -> c)
                                .thenAccept((pair) -> {
                                    HttpRequest request = pair.t.request();
                                    byte[] requestBody = bodies.get(request);
                                    check(Arrays.equals(requestBody, pair.u),
                                            "bodies not equal:[" + bytesToHexString(requestBody)
                                                    + "] [" + bytesToHexString(pair.u) + "]");

                                });
            }

            try {
                // wait for them all to complete and throw exception in case of error
                CompletableFuture.allOf(results).join();
                done = true;
            } catch (CompletionException e) {
                if (!Platform.isWindows()) throw e;
                if (LIMIT.get() < REQUESTS) throw e;
                Throwable cause = e;
                while ((cause = cause.getCause()) != null) {
                    if (cause instanceof ConnectException) {
                        // try again, limit concurrency by half
                        COUNT.set(0);
                        LIMIT.set(REQUESTS/2);
                        System.out.println("*** Retrying due to " + cause);
                        continue LOOP;
                    }
                }
                throw e;
            }
        } while (!done);
    }

    static <T> CompletableFuture<T> completedWithIOException(String message) {
        return CompletableFuture.failedFuture(new IOException(message));
    }

    static String bytesToHexString(byte[] bytes) {
        if (bytes == null)
            return "null";

        StringBuilder sb = new StringBuilder(bytes.length * 2);

        Formatter formatter = new Formatter(sb);
        for (byte b : bytes) {
            formatter.format("%02x", b);
        }

        return sb.toString();
    }

    record Pair<T,U>(T t, U u) { }

    /**
     * A simple limiter for controlling the number of requests to be run in
     * parallel whenOkToSend() is called which returns a CF<Void> that allows
     * each individual request to proceed, or block temporarily (blocking occurs
     * on the waiters list here. As each request actually completes
     * requestComplete() is called to notify this object, and allow some
     * requests to continue.
     */
    static class RequestLimiter {

        static final CompletableFuture<Void> COMPLETED_FUTURE =
                CompletableFuture.completedFuture(null);

        final int maxnumber;
        final LinkedList<CompletableFuture<Void>> waiters;
        int number;
        boolean blocked;

        RequestLimiter(int maximum) {
            waiters = new LinkedList<>();
            maxnumber = maximum;
        }

        synchronized void requestComplete() {
            number--;
            // don't unblock until number of requests has halved.
            if ((blocked && number <= maxnumber / 2) ||
                        (!blocked && waiters.size() > 0)) {
                int toRelease = Math.min(maxnumber - number, waiters.size());
                for (int i=0; i<toRelease; i++) {
                    CompletableFuture<Void> f = waiters.remove();
                    number ++;
                    f.complete(null);
                }
                blocked = number >= maxnumber;
            }
        }

        synchronized CompletableFuture<Void> whenOkToSend() {
            if (blocked || number + 1 >= maxnumber) {
                blocked = true;
                CompletableFuture<Void> r = new CompletableFuture<>();
                waiters.add(r);
                return r;
            } else {
                number++;
                return COMPLETED_FUTURE;
            }
        }
    }

    static void check(boolean cond, Object... msg) {
        if (cond)
            return;
        StringBuilder sb = new StringBuilder();
        for (Object o : msg)
            sb.append(o);
        throw new RuntimeException(sb.toString());
    }

    static class Configurator extends HttpsConfigurator {
        public Configurator(SSLContext ctx) {
            super(ctx);
        }

        public void configure(HttpsParameters params) {
            params.setSSLParameters(getSSLContext().getSupportedSSLParameters());
        }
    }
}
