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

import com.sun.net.httpserver.BasicAuthenticator;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsParameters;
import com.sun.net.httpserver.HttpsServer;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.math.BigInteger;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.StandardSocketOptions;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.HexFormat;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.net.ssl.SSLContext;

import jdk.httpclient.test.lib.common.HttpServerAdapters.AbstractHttpAuthFilter.HttpAuthMode;
import sun.net.www.HeaderParser;
import java.net.http.HttpClient.Version;
import jdk.httpclient.test.lib.common.HttpServerAdapters;
import jdk.httpclient.test.lib.http2.Http2TestServer;

/**
 * A simple HTTP server that supports Basic or Digest authentication.
 * By default this server will echo back whatever is present
 * in the request body. Note that the Digest authentication is
 * a test implementation implemented only for tests purposes.
 * @author danielfuchs
 */
public abstract class DigestEchoServer implements HttpServerAdapters {

    public static final boolean DEBUG =
            Boolean.parseBoolean(System.getProperty("test.debug", "false"));
    public static final boolean NO_LINGER =
            Boolean.parseBoolean(System.getProperty("test.nolinger", "false"));
    public static final boolean TUNNEL_REQUIRES_HOST =
            Boolean.parseBoolean(System.getProperty("test.requiresHost", "false"));
    public enum HttpAuthType {
        SERVER, PROXY, SERVER307, PROXY305;
        /* add PROXY_AND_SERVER and SERVER_PROXY_NONE */
        public HttpAuthMode authMode() {
            return switch (this) {
                case SERVER, SERVER307 -> HttpAuthMode.SERVER;
                case PROXY, PROXY305 -> HttpAuthMode.PROXY;
            };
        }
    };
    public enum HttpAuthSchemeType { NONE, BASICSERVER, BASIC, DIGEST };
    public static final HttpAuthType DEFAULT_HTTP_AUTH_TYPE = HttpAuthType.SERVER;
    public static final String DEFAULT_PROTOCOL_TYPE = "https";
    public static final HttpAuthSchemeType DEFAULT_SCHEME_TYPE = HttpAuthSchemeType.DIGEST;

    public static class HttpTestAuthenticator extends Authenticator {
        private final String realm;
        private final String username;
        // Used to prevent incrementation of 'count' when calling the
        // authenticator from the server side.
        private final ThreadLocal<Boolean> skipCount = new ThreadLocal<>();
        // count will be incremented every time getPasswordAuthentication()
        // is called from the client side.
        final AtomicInteger count = new AtomicInteger();

        public HttpTestAuthenticator(String realm, String username) {
            this.realm = realm;
            this.username = username;
        }
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            if (skipCount.get() == null || skipCount.get().booleanValue() == false) {
                System.out.println("Authenticator called: " + count.incrementAndGet());
            }
            return new PasswordAuthentication(getUserName(),
                    new char[] {'d','e','n', 't'});
        }
        // Called by the server side to get the password of the user
        // being authentified.
        public final char[] getPassword(String user) {
            if (user.equals(username)) {
                skipCount.set(Boolean.TRUE);
                try {
                    return getPasswordAuthentication().getPassword();
                } finally {
                    skipCount.set(Boolean.FALSE);
                }
            }
            throw new SecurityException("User unknown: " + user);
        }
        public final String getUserName() {
            return username;
        }
        public final String getRealm() {
            return realm;
        }
    }

    public static final HttpTestAuthenticator AUTHENTICATOR;
    static {
        AUTHENTICATOR = new HttpTestAuthenticator("earth", "arthur");
    }


    final HttpTestServer       serverImpl; // this server endpoint
    final DigestEchoServer     redirect;   // the target server where to redirect 3xx
    final HttpTestHandler      delegate;   // unused
    final String               key;

    DigestEchoServer(String key,
                             HttpTestServer server,
                             DigestEchoServer target,
                             HttpTestHandler delegate) {
        this.key = key;
        this.serverImpl = server;
        this.redirect = target;
        this.delegate = delegate;
    }

    public static void main(String[] args)
            throws IOException {

        DigestEchoServer server = create(Version.HTTP_1_1,
                DEFAULT_PROTOCOL_TYPE,
                DEFAULT_HTTP_AUTH_TYPE,
                AUTHENTICATOR,
                DEFAULT_SCHEME_TYPE);
        try {
            System.out.println("Server created at " + server.getAddress());
            System.out.println("Strike <Return> to exit");
            System.in.read();
        } finally {
            System.out.println("stopping server");
            server.stop();
        }
    }

    private static String toString(HttpTestRequestHeaders headers) {
        return headers.entrySet().stream()
                .map((e) -> e.getKey() + ": " + e.getValue())
                .collect(Collectors.joining("\n"));
    }

    public static DigestEchoServer create(Version version,
                                          String protocol,
                                          HttpAuthType authType,
                                          HttpAuthSchemeType schemeType)
            throws IOException {
        return create(version, protocol, authType, AUTHENTICATOR, schemeType);
    }

    public static DigestEchoServer create(Version version,
                                          String protocol,
                                          HttpAuthType authType,
                                          HttpTestAuthenticator auth,
                                          HttpAuthSchemeType schemeType)
            throws IOException {
        return create(version, protocol, authType, auth, schemeType, null);
    }

    public static DigestEchoServer create(Version version,
                                        String protocol,
                                        HttpAuthType authType,
                                        HttpTestAuthenticator auth,
                                        HttpAuthSchemeType schemeType,
                                        HttpTestHandler delegate)
            throws IOException {
        Objects.requireNonNull(authType);
        Objects.requireNonNull(auth);
        switch(authType) {
            // A server that performs Server Digest authentication.
            case SERVER: return createServer(version, protocol, authType, auth,
                                             schemeType, delegate, "/");
            // A server that pretends to be a Proxy and performs
            // Proxy Digest authentication. If protocol is HTTPS,
            // then this will create a HttpsProxyTunnel that will
            // handle the CONNECT request for tunneling.
            case PROXY: return createProxy(version, protocol, authType, auth,
                                           schemeType, delegate, "/");
            // A server that sends 307 redirect to a server that performs
            // Digest authentication.
            // Note: 301 doesn't work here because it transforms POST into GET.
            case SERVER307: return createServerAndRedirect(version,
                                                        protocol,
                                                        HttpAuthType.SERVER,
                                                        auth, schemeType,
                                                        delegate, 307);
            // A server that sends 305 redirect to a proxy that performs
            // Digest authentication.
            // Note: this is not correctly stubbed/implemented in this test.
            case PROXY305:  return createServerAndRedirect(version,
                                                        protocol,
                                                        HttpAuthType.PROXY,
                                                        auth, schemeType,
                                                        delegate, 305);
            default:
                throw new InternalError("Unknown server type: " + authType);
        }
    }


    /**
     * The SocketBindableFactory ensures that the local port used by an HttpServer
     * or a proxy ServerSocket previously created by the current test/VM will not
     * get reused by a subsequent test in the same VM.
     * This is to avoid having the test client trying to reuse cached connections.
     */
    private static abstract class SocketBindableFactory<B> {
        private static final int MAX = 10;
        private static final CopyOnWriteArrayList<String> addresses =
                new CopyOnWriteArrayList<>();
        protected B createInternal() throws IOException {
            final int max = addresses.size() + MAX;
            final List<B> toClose = new ArrayList<>();
            try {
                for (int i = 1; i <= max; i++) {
                    B bindable = createBindable();
                    InetSocketAddress address = getAddress(bindable);
                    String key = "localhost:" + address.getPort();
                    if (addresses.addIfAbsent(key)) {
                        System.out.println("Socket bound to: " + key
                                + " after " + i + " attempt(s)");
                        return bindable;
                    }
                    System.out.println("warning: address " + key
                            + " already used. Retrying bind.");
                    // keep the port bound until we get a port that we haven't
                    // used already
                    toClose.add(bindable);
                }
            } finally {
                // if we had to retry, then close the socket we're not
                // going to use.
                for (B b : toClose) {
                    try { close(b); } catch (Exception x) { /* ignore */ }
                }
            }
            throw new IOException("Couldn't bind socket after " + max + " attempts: "
                    + "addresses used before: " + addresses);
        }

        protected abstract B createBindable() throws IOException;

        protected abstract InetSocketAddress getAddress(B bindable);

        protected abstract void close(B bindable) throws IOException;
    }

    /*
     * Used to create ServerSocket for a proxy.
     */
    private static final class ServerSocketFactory
    extends SocketBindableFactory<ServerSocket> {
        private static final ServerSocketFactory instance = new ServerSocketFactory();

        static ServerSocket create() throws IOException {
            return instance.createInternal();
        }

        @Override
        protected ServerSocket createBindable() throws IOException {
            ServerSocket ss = new ServerSocket();
            ss.setReuseAddress(false);
            ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
            return ss;
        }

        @Override
        protected InetSocketAddress getAddress(ServerSocket socket) {
            return new InetSocketAddress(socket.getInetAddress(), socket.getLocalPort());
        }

        @Override
        protected void close(ServerSocket socket) throws IOException {
            socket.close();
        }
    }

    /*
     * Used to create HttpServer
     */
    private static abstract class H1ServerFactory<S extends HttpServer>
            extends SocketBindableFactory<S> {
        @Override
        protected S createBindable() throws IOException {
            S server = newHttpServer();
            server.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0);
            return server;
        }

        @Override
        protected InetSocketAddress getAddress(S server) {
            return server.getAddress();
        }

        @Override
        protected void close(S server) throws IOException {
            server.stop(1);
        }

        /*
         * Returns a HttpServer or a HttpsServer in different subclasses.
         */
        protected abstract S newHttpServer() throws IOException;
    }

    /*
     * Used to create Http2TestServer
     */
    private static abstract class H2ServerFactory<S extends Http2TestServer>
            extends SocketBindableFactory<S> {
        @Override
        protected S createBindable() throws IOException {
            final S server;
            try {
                server = newHttpServer();
            } catch (IOException io) {
                throw io;
            } catch (Exception x) {
                throw new IOException(x);
            }
            return server;
        }

        @Override
        protected InetSocketAddress getAddress(S server) {
            return server.getAddress();
        }

        @Override
        protected void close(S server) throws IOException {
            server.stop();
        }

        /*
         * Returns a HttpServer or a HttpsServer in different subclasses.
         */
        protected abstract S newHttpServer() throws Exception;
    }

    private static final class Http2ServerFactory extends H2ServerFactory<Http2TestServer> {
        private static final Http2ServerFactory instance = new Http2ServerFactory();

        static Http2TestServer create() throws IOException {
            return instance.createInternal();
        }

        @Override
        protected Http2TestServer newHttpServer() throws Exception {
            return new Http2TestServer("localhost", false, 0);
        }
    }

    private static final class Https2ServerFactory extends H2ServerFactory<Http2TestServer> {
        private static final Https2ServerFactory instance = new Https2ServerFactory();

        static Http2TestServer create() throws IOException {
            return instance.createInternal();
        }

        @Override
        protected Http2TestServer newHttpServer() throws Exception {
            return new Http2TestServer("localhost", true, 0);
        }
    }

    private static final class Http1ServerFactory extends H1ServerFactory<HttpServer> {
        private static final Http1ServerFactory instance = new Http1ServerFactory();

        static HttpServer create() throws IOException {
            return instance.createInternal();
        }

        @Override
        protected HttpServer newHttpServer() throws IOException {
            return HttpServer.create();
        }
    }

    private static final class Https1ServerFactory extends H1ServerFactory<HttpsServer> {
        private static final Https1ServerFactory instance = new Https1ServerFactory();

        static HttpsServer create() throws IOException {
            return instance.createInternal();
        }

        @Override
        protected HttpsServer newHttpServer() throws IOException {
            return HttpsServer.create();
        }
    }

    static Http2TestServer createHttp2Server(String protocol) throws IOException {
        final Http2TestServer server;
        if ("http".equalsIgnoreCase(protocol)) {
            server = Http2ServerFactory.create();
        } else if ("https".equalsIgnoreCase(protocol)) {
            server = Https2ServerFactory.create();
        } else {
            throw new InternalError("unsupported protocol: " + protocol);
        }
        return server;
    }

    static HttpTestServer createHttpServer(Version version, String protocol)
            throws IOException
    {
        switch(version) {
            case HTTP_1_1:
                return HttpTestServer.of(createHttp1Server(protocol));
            case HTTP_2:
                return HttpTestServer.of(createHttp2Server(protocol));
            default:
                throw new InternalError("Unexpected version: " + version);
        }
    }

    static HttpServer createHttp1Server(String protocol) throws IOException {
        final HttpServer server;
        if ("http".equalsIgnoreCase(protocol)) {
            server = Http1ServerFactory.create();
        } else if ("https".equalsIgnoreCase(protocol)) {
            server = configure(Https1ServerFactory.create());
        } else {
            throw new InternalError("unsupported protocol: " + protocol);
        }
        return server;
    }

    static HttpsServer configure(HttpsServer server) throws IOException {
        try {
            SSLContext ctx = SSLContext.getDefault();
            server.setHttpsConfigurator(new Configurator(ctx));
        } catch (NoSuchAlgorithmException ex) {
            throw new IOException(ex);
        }
        return server;
    }

    static BasicAuthenticator toBasicAuthenticator(HttpTestAuthenticator auth) {
        final String realm = auth.getRealm();
        return new BasicAuthenticator(realm) {
            @Override
            public boolean checkCredentials(String username, String pwd) {
                return auth.getUserName().equals(username)
                        && new String(auth.getPassword(username)).equals(pwd);
            }
        };
    }

    static void setContextAuthenticator(HttpTestContext ctxt,
                                        HttpTestAuthenticator auth) {

        ctxt.setAuthenticator(toBasicAuthenticator(auth));
    }

    public static DigestEchoServer createServer(Version version,
                                        String protocol,
                                        HttpAuthType authType,
                                        HttpTestAuthenticator auth,
                                        HttpAuthSchemeType schemeType,
                                        HttpTestHandler delegate,
                                        String path)
            throws IOException {
        Objects.requireNonNull(authType);
        Objects.requireNonNull(auth);

        HttpTestServer impl = createHttpServer(version, protocol);
        String key = String.format("DigestEchoServer[PID=%s,PORT=%s]:%s:%s:%s:%s",
                ProcessHandle.current().pid(),
                impl.getAddress().getPort(),
                version, protocol, authType, schemeType);
        final DigestEchoServer server = new DigestEchoServerImpl(key, impl, null, delegate);
        final HttpTestHandler handler =
                server.createHandler(schemeType, auth, authType, false);
        HttpTestContext context = impl.addHandler(handler, path);
        server.configureAuthentication(context, schemeType, auth, authType);
        impl.start();
        return server;
    }

    public static DigestEchoServer createProxy(Version version,
                                        String protocol,
                                        HttpAuthType authType,
                                        HttpTestAuthenticator auth,
                                        HttpAuthSchemeType schemeType,
                                        HttpTestHandler delegate,
                                        String path)
            throws IOException {
        Objects.requireNonNull(authType);
        Objects.requireNonNull(auth);

        if (version == Version.HTTP_2 && protocol.equalsIgnoreCase("http")) {
            System.out.println("WARNING: can't use HTTP/1.1 proxy with unsecure HTTP/2 server");
            version = Version.HTTP_1_1;
        }
        HttpTestServer impl = createHttpServer(version, protocol);
        String key = String.format("DigestEchoServer[PID=%s,PORT=%s]:%s:%s:%s:%s",
                ProcessHandle.current().pid(),
                impl.getAddress().getPort(),
                version, protocol, authType, schemeType);
        final DigestEchoServer server = "https".equalsIgnoreCase(protocol)
                ? new HttpsProxyTunnel(key, impl, null, delegate)
                : new DigestEchoServerImpl(key, impl, null, delegate);

        final HttpTestHandler hh = server.createHandler(HttpAuthSchemeType.NONE,
                                         null, HttpAuthType.SERVER,
                                         server instanceof HttpsProxyTunnel);
        HttpTestContext ctxt = impl.addHandler(hh, path);
        server.configureAuthentication(ctxt, schemeType, auth, authType);
        impl.start();

        return server;
    }

    public static DigestEchoServer createServerAndRedirect(
                                        Version version,
                                        String protocol,
                                        HttpAuthType targetAuthType,
                                        HttpTestAuthenticator auth,
                                        HttpAuthSchemeType schemeType,
                                        HttpTestHandler targetDelegate,
                                        int code300)
            throws IOException {
        Objects.requireNonNull(targetAuthType);
        Objects.requireNonNull(auth);

        // The connection between client and proxy can only
        // be a plain connection: SSL connection to proxy
        // is not supported by our client connection.
        String targetProtocol = targetAuthType == HttpAuthType.PROXY
                                          ? "http"
                                          : protocol;
        DigestEchoServer redirectTarget =
                (targetAuthType == HttpAuthType.PROXY)
                ? createProxy(version, protocol, targetAuthType,
                              auth, schemeType, targetDelegate, "/")
                : createServer(version, targetProtocol, targetAuthType,
                               auth, schemeType, targetDelegate, "/");
        HttpTestServer impl = createHttpServer(version, protocol);
        String key = String.format("RedirectingServer[PID=%s,PORT=%s]:%s:%s:%s:%s",
                ProcessHandle.current().pid(),
                impl.getAddress().getPort(),
                version, protocol,
                HttpAuthType.SERVER, code300)
                + "->" + redirectTarget.key;
        final DigestEchoServer redirectingServer =
                 new DigestEchoServerImpl(key, impl, redirectTarget, null);
        InetSocketAddress redirectAddr = redirectTarget.getAddress();
        URL locationURL = url(targetProtocol, redirectAddr, "/");
        final HttpTestHandler hh = redirectingServer.create300Handler(key, locationURL,
                                             HttpAuthType.SERVER, code300);
        impl.addHandler(hh,"/");
        impl.start();
        return redirectingServer;
    }

    public abstract InetSocketAddress getServerAddress();
    public abstract InetSocketAddress getProxyAddress();
    public abstract InetSocketAddress getAddress();
    public abstract void stop();
    public abstract Version getServerVersion();

    private static class DigestEchoServerImpl extends DigestEchoServer {
        DigestEchoServerImpl(String key,
                             HttpTestServer server,
                             DigestEchoServer target,
                             HttpTestHandler delegate) {
            super(key, Objects.requireNonNull(server), target, delegate);
        }

        public InetSocketAddress getAddress() {
            return new InetSocketAddress(InetAddress.getLoopbackAddress(),
                    serverImpl.getAddress().getPort());
        }

        public InetSocketAddress getServerAddress() {
            return new InetSocketAddress(InetAddress.getLoopbackAddress(),
                    serverImpl.getAddress().getPort());
        }

        public InetSocketAddress getProxyAddress() {
            return new InetSocketAddress(InetAddress.getLoopbackAddress(),
                    serverImpl.getAddress().getPort());
        }

        public Version getServerVersion() {
            return serverImpl.getVersion();
        }

        public void stop() {
            serverImpl.stop();
            if (redirect != null) {
                redirect.stop();
            }
        }
    }

    protected void writeResponse(HttpTestExchange he) throws IOException {
        if (delegate == null) {
            he.sendResponseHeaders(HttpURLConnection.HTTP_OK, -1);
            he.getResponseBody().write(he.getRequestBody().readAllBytes());
        } else {
            delegate.handle(he);
        }
    }

    private HttpTestHandler createHandler(HttpAuthSchemeType schemeType,
                                      HttpTestAuthenticator auth,
                                      HttpAuthType authType,
                                      boolean tunelled) {
        return new HttpNoAuthHandler(key, authType, tunelled);
    }

    void configureAuthentication(HttpTestContext ctxt,
                                 HttpAuthSchemeType schemeType,
                                 HttpTestAuthenticator auth,
                                 HttpAuthType authType) {
        switch(schemeType) {
            case DIGEST:
                // DIGEST authentication is handled by the filter.
                ctxt.addFilter(new HttpDigestFilter(key, auth, authType));
                break;
            case BASIC:
                // BASIC authentication is handled by the filter.
                ctxt.addFilter(new HttpBasicFilter(key, auth, authType));
                break;
            case BASICSERVER:
                switch(authType) {
                    case PROXY: case PROXY305:
                        // HttpServer can't support Proxy-type authentication
                        // => we do as if BASIC had been specified, and we will
                        //    handle authentication in the handler.
                        ctxt.addFilter(new HttpBasicFilter(key, auth, authType));
                        break;
                    case SERVER: case SERVER307:
                        if (ctxt.getVersion() == Version.HTTP_1_1) {
                            // Basic authentication is handled by HttpServer
                            // directly => the filter should not perform
                            // authentication again.
                            setContextAuthenticator(ctxt, auth);
                            ctxt.addFilter(new HttpNoAuthFilter(key, authType));
                        } else {
                            ctxt.addFilter(new HttpBasicFilter(key, auth, authType));
                        }
                        break;
                    default:
                        throw new InternalError(key + ": Invalid combination scheme="
                             + schemeType + " authType=" + authType);
                }
                break;
            case NONE:
                // No authentication at all.
                ctxt.addFilter(new HttpNoAuthFilter(key, authType));
                break;
            default:
                throw new InternalError(key + ": No such scheme: " + schemeType);
        }
    }

    private HttpTestHandler create300Handler(String key, URL proxyURL,
                                             HttpAuthType type, int code300)
            throws MalformedURLException
    {
        return new Http3xxHandler(key, proxyURL, type, code300);
    }


    // WARNING: This is not a full fledged implementation of DIGEST.
    // It does contain bugs and inaccuracy.
    final static class DigestResponse {
        final String realm;
        final String username;
        final String nonce;
        final String cnonce;
        final String nc;
        final String uri;
        final String algorithm;
        final String response;
        final String qop;
        final String opaque;

        public DigestResponse(String realm, String username, String nonce,
                              String cnonce, String nc, String uri,
                              String algorithm, String qop, String opaque,
                              String response) {
            this.realm = realm;
            this.username = username;
            this.nonce = nonce;
            this.cnonce = cnonce;
            this.nc = nc;
            this.uri = uri;
            this.algorithm = algorithm;
            this.qop = qop;
            this.opaque = opaque;
            this.response = response;
        }

        String getAlgorithm(String defval) {
            return algorithm == null ? defval : algorithm;
        }
        String getQoP(String defval) {
            return qop == null ? defval : qop;
        }

        // Code stolen from DigestAuthentication:

        private static String encode(String src, char[] passwd, MessageDigest md) {
            try {
                md.update(src.getBytes("ISO-8859-1"));
            } catch (java.io.UnsupportedEncodingException uee) {
                assert false;
            }
            if (passwd != null) {
                byte[] passwdBytes = new byte[passwd.length];
                for (int i=0; i<passwd.length; i++)
                    passwdBytes[i] = (byte)passwd[i];
                md.update(passwdBytes);
                Arrays.fill(passwdBytes, (byte)0x00);
            }
            byte[] digest = md.digest();
            return HexFormat.of().formatHex(digest);
        }

        public static String computeDigest(boolean isRequest,
                                           String reqMethod,
                                           char[] password,
                                           DigestResponse params)
            throws NoSuchAlgorithmException
        {

            String A1, HashA1;
            String algorithm = params.getAlgorithm("MD5");
            boolean md5sess = algorithm.equalsIgnoreCase ("MD5-sess");

            MessageDigest md = MessageDigest.getInstance(md5sess?"MD5":algorithm);

            if (params.username == null) {
                throw new IllegalArgumentException("missing username");
            }
            if (params.realm == null) {
                throw new IllegalArgumentException("missing realm");
            }
            if (params.uri == null) {
                throw new IllegalArgumentException("missing uri");
            }
            if (params.nonce == null) {
                throw new IllegalArgumentException("missing nonce");
            }

            A1 = params.username + ":" + params.realm + ":";
            HashA1 = encode(A1, password, md);

            String A2;
            if (isRequest) {
                A2 = reqMethod + ":" + params.uri;
            } else {
                A2 = ":" + params.uri;
            }
            String HashA2 = encode(A2, null, md);
            String combo, finalHash;

            if ("auth".equals(params.qop)) { /* RRC2617 when qop=auth */
                if (params.cnonce == null) {
                    throw new IllegalArgumentException("missing nonce");
                }
                if (params.nc == null) {
                    throw new IllegalArgumentException("missing nonce");
                }
                combo = HashA1+ ":" + params.nonce + ":" + params.nc + ":" +
                            params.cnonce + ":auth:" +HashA2;

            } else { /* for compatibility with RFC2069 */
                combo = HashA1 + ":" +
                           params.nonce + ":" +
                           HashA2;
            }
            finalHash = encode(combo, null, md);
            return finalHash;
        }

        public static DigestResponse create(String raw) {
            String username, realm, nonce, nc, uri, response, cnonce,
                   algorithm, qop, opaque;
            HeaderParser parser = new HeaderParser(raw);
            username = parser.findValue("username");
            realm = parser.findValue("realm");
            nonce = parser.findValue("nonce");
            nc = parser.findValue("nc");
            uri = parser.findValue("uri");
            cnonce = parser.findValue("cnonce");
            response = parser.findValue("response");
            algorithm = parser.findValue("algorithm");
            qop = parser.findValue("qop");
            opaque = parser.findValue("opaque");
            return new DigestResponse(realm, username, nonce, cnonce, nc, uri,
                                      algorithm, qop, opaque, response);
        }

    }

    private static class HttpNoAuthFilter extends AbstractHttpAuthFilter {

        static String type(String key, HttpAuthType authType) {
            String type = authType.authMode() == HttpAuthMode.SERVER
                    ? "NoAuth Server Filter" : "NoAuth Proxy Filter";
            return "["+type+"]:"+key;
        }

        public HttpNoAuthFilter(String key, HttpAuthType authType) {
            super(authType.authMode(), type(key, authType));
        }

        @Override
        protected boolean isAuthentified(HttpTestExchange he) throws IOException {
            return true;
        }

        @Override
        protected void requestAuthentication(HttpTestExchange he) throws IOException {
            throw new InternalError("Should not com here");
        }

        @Override
        public String description() {
            return "Passthrough Filter";
        }

    }

    // An HTTP Filter that performs Basic authentication
    private static class HttpBasicFilter extends HttpBasicAuthFilter {

        static String type(String key, HttpAuthType authType) {
            String type = authType.authMode() == HttpAuthMode.SERVER
                    ? "Basic Server Filter" : "Basic Proxy Filter";
            return "["+type+"]:"+key;
        }

        public HttpBasicFilter(String key, HttpTestAuthenticator auth,
                               HttpAuthType authType) {
            super(toBasicAuthenticator(auth), authType.authMode(), type(key, authType));
        }

        @Override
        public String description() {
            return "Filter for BASIC authentication: " + type();
        }

    }


    // An HTTP Filter that performs Digest authentication
    // WARNING: This is not a full fledged implementation of DIGEST.
    // It does contain bugs and inaccuracy.
    private static class HttpDigestFilter extends AbstractHttpAuthFilter {

        static String type(String key, HttpAuthType authType) {
            String type = authType.authMode() == HttpAuthMode.SERVER
                    ? "Digest Server Filter" : "Digest Proxy Filter";
            return "["+type+"]:"+key;
        }

        // This is a very basic DIGEST - used only for the purpose of testing
        // the client implementation. Therefore we can get away with never
        // updating the server nonce as it makes the implementation of the
        // server side digest simpler.
        private final HttpTestAuthenticator auth;
        private final byte[] nonce;
        private final String ns;
        private final String type;
        public HttpDigestFilter(String key, HttpTestAuthenticator auth, HttpAuthType authType) {
            super(authType.authMode(), type(key, authType));
            this.auth = auth;
            nonce = new byte[16];
            new Random(Instant.now().toEpochMilli()).nextBytes(nonce);
            ns = new BigInteger(1, nonce).toString(16);
            this.type = type();
        }

        @Override
        protected void requestAuthentication(HttpTestExchange he)
                throws IOException {
            String separator;
            Version v = he.getExchangeVersion();
            if (v == Version.HTTP_1_1) {
                separator = "\r\n    ";
            } else if (v == Version.HTTP_2) {
                separator = " ";
            } else {
                throw new InternalError(String.valueOf(v));
            }
            String headerName = getAuthenticate();
            String headerValue = "Digest realm=\"" + auth.getRealm() + "\","
                    + separator + "qop=\"auth\","
                    + separator + "nonce=\"" + ns +"\"";
            he.getResponseHeaders().addHeader(headerName, headerValue);
            System.out.println(type + ": Requesting Digest Authentication, "
                               + headerName + " : " + headerValue);
        }

        @Override
        protected boolean isAuthentified(HttpTestExchange he) {
            if (he.getRequestHeaders().containsKey(getAuthorization())) {
                List<String> authorization = he.getRequestHeaders().get(getAuthorization());
                for (String a : authorization) {
                    System.out.println(type + ": processing " + a);
                    int sp = a.indexOf(' ');
                    if (sp < 0) return false;
                    String scheme = a.substring(0, sp);
                    if (!"Digest".equalsIgnoreCase(scheme)) {
                        System.out.println(type + ": Unsupported scheme '" + scheme +"'");
                        return false;
                    }
                    if (a.length() <= sp+1) {
                        System.out.println(type + ": value too short for '" + scheme +"'");
                        return false;
                    }
                    a = a.substring(sp+1);
                    DigestResponse dgr = DigestResponse.create(a);
                    return validate(he.getRequestURI(), he.getRequestMethod(), dgr);
                }
                return false;
            }
            return false;
        }

        boolean validate(URI uri, String reqMethod, DigestResponse dg) {
            if (!"MD5".equalsIgnoreCase(dg.getAlgorithm("MD5"))) {
                System.out.println(type + ": Unsupported algorithm "
                                   + dg.algorithm);
                return false;
            }
            if (!"auth".equalsIgnoreCase(dg.getQoP("auth"))) {
                System.out.println(type + ": Unsupported qop "
                                   + dg.qop);
                return false;
            }
            try {
                if (!dg.nonce.equals(ns)) {
                    System.out.println(type + ": bad nonce returned by client: "
                                    + nonce + " expected " + ns);
                    return false;
                }
                if (dg.response == null) {
                    System.out.println(type + ": missing digest response.");
                    return false;
                }
                char[] pa = auth.getPassword(dg.username);
                return verify(uri, reqMethod, dg, pa);
            } catch(IllegalArgumentException | SecurityException
                    | NoSuchAlgorithmException e) {
                System.out.println(type + ": " + e.getMessage());
                return false;
            }
        }


        boolean verify(URI uri, String reqMethod, DigestResponse dg, char[] pw)
            throws NoSuchAlgorithmException {
            String response = DigestResponse.computeDigest(true, reqMethod, pw, dg);
            if (!dg.response.equals(response)) {
                System.out.println(type + ": bad response returned by client: "
                                    + dg.response + " expected " + response);
                return false;
            } else {
                // A real server would also verify the uri=<request-uri>
                // parameter - but this is just a test...
                System.out.println(type + ": verified response " + response);
            }
            return true;
        }


        @Override
        public String description() {
            return "Filter for DIGEST authentication: " + type;
        }
    }

    // Abstract HTTP handler class.
    private abstract static class AbstractHttpHandler implements HttpTestHandler {

        final HttpAuthType authType;
        final String type;
        public AbstractHttpHandler(HttpAuthType authType, String type) {
            this.authType = authType;
            this.type = type;
        }

        String getLocation() {
            return "Location";
        }

        @Override
        public void handle(HttpTestExchange he) throws IOException {
            try {
                sendResponse(he);
            } catch (RuntimeException | Error | IOException t) {
               System.err.println(type
                    + ": Unexpected exception while handling request: " + t);
               t.printStackTrace(System.err);
               throw t;
            } finally {
                he.close();
            }
        }

        protected abstract void sendResponse(HttpTestExchange he) throws IOException;

    }

    static String stype(String type, String key, HttpAuthType authType, boolean tunnelled) {
        type = type + (authType == HttpAuthType.SERVER
                       ? " Server" : " Proxy")
                + (tunnelled ? " Tunnelled" : "");
        return "["+type+"]:"+key;
    }

    private class HttpNoAuthHandler extends AbstractHttpHandler {

        // true if this server is behind a proxy tunnel.
        final boolean tunnelled;
        public HttpNoAuthHandler(String key, HttpAuthType authType, boolean tunnelled) {
            super(authType, stype("NoAuth", key, authType, tunnelled));
            this.tunnelled = tunnelled;
        }

        @Override
        protected void sendResponse(HttpTestExchange he) throws IOException {
            if (DEBUG) {
                System.out.println(type + ": headers are: "
                        + DigestEchoServer.toString(he.getRequestHeaders()));
            }
            if (authType == HttpAuthType.SERVER && tunnelled) {
                // Verify that the client doesn't send us proxy-* headers
                // used to establish the proxy tunnel
                Optional<String> proxyAuth = he.getRequestHeaders()
                        .keySet().stream()
                        .filter("proxy-authorization"::equalsIgnoreCase)
                        .findAny();
                if (proxyAuth.isPresent()) {
                    System.out.println(type + " found "
                            + proxyAuth.get() + ": failing!");
                    throw new IOException(proxyAuth.get()
                            + " found by " + type + " for "
                            + he.getRequestURI());
                }
            }
            DigestEchoServer.this.writeResponse(he);
        }

    }

    // A dummy HTTP Handler that redirects all incoming requests
    // by sending a back 3xx response code (301, 305, 307 etc..)
    private class Http3xxHandler extends AbstractHttpHandler {

        private final URL redirectTargetURL;
        private final int code3XX;
        public Http3xxHandler(String key, URL proxyURL, HttpAuthType authType, int code300) {
            super(authType, stype("Server" + code300, key, authType, false));
            this.redirectTargetURL = proxyURL;
            this.code3XX = code300;
        }

        int get3XX() {
            return code3XX;
        }

        @Override
        public void sendResponse(HttpTestExchange he) throws IOException {
            System.out.println(type + ": Got " + he.getRequestMethod()
                    + ": " + he.getRequestURI()
                    + "\n" + DigestEchoServer.toString(he.getRequestHeaders()));
            System.out.println(type + ": Redirecting to "
                               + (authType == HttpAuthType.PROXY305
                                    ? "proxy" : "server"));
            he.getResponseHeaders().addHeader(getLocation(),
                redirectTargetURL.toExternalForm().toString());
            he.sendResponseHeaders(get3XX(), -1);
            System.out.println(type + ": Sent back " + get3XX() + " "
                 + getLocation() + ": " + redirectTargetURL.toExternalForm().toString());
        }
    }

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

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

    static final long start = System.nanoTime();
    public static String now() {
        long now = System.nanoTime() - start;
        long secs = now / 1000_000_000;
        long mill = (now % 1000_000_000) / 1000_000;
        long nan = now % 1000_000;
        return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan);
    }

    static class  ProxyAuthorization {
        final HttpAuthSchemeType schemeType;
        final HttpTestAuthenticator authenticator;
        private final byte[] nonce;
        private final String ns;
        private final String key;

        ProxyAuthorization(String key, HttpAuthSchemeType schemeType, HttpTestAuthenticator auth) {
            this.key = key;
            this.schemeType = schemeType;
            this.authenticator = auth;
            nonce = new byte[16];
            new Random(Instant.now().toEpochMilli()).nextBytes(nonce);
            ns = new BigInteger(1, nonce).toString(16);
        }

        String doBasic(Optional<String> authorization) {
            String offset = "proxy-authorization: basic ";
            String authstring = authorization.orElse("");
            if (!authstring.toLowerCase(Locale.US).startsWith(offset)) {
                return "Proxy-Authenticate: BASIC " + "realm=\""
                        + authenticator.getRealm() +"\"";
            }
            authstring = authstring
                    .substring(offset.length())
                    .trim();
            byte[] base64 = Base64.getDecoder().decode(authstring);
            String up = new String(base64, StandardCharsets.UTF_8);
            int colon = up.indexOf(':');
            if (colon < 1) {
                return "Proxy-Authenticate: BASIC " + "realm=\""
                        + authenticator.getRealm() +"\"";
            }
            String u = up.substring(0, colon);
            String p = up.substring(colon+1);
            char[] pw = authenticator.getPassword(u);
            if (!p.equals(new String(pw))) {
                return "Proxy-Authenticate: BASIC " + "realm=\""
                        + authenticator.getRealm() +"\"";
            }
            System.out.println(now() + key + " Proxy basic authentication success");
            return null;
        }

        String doDigest(Optional<String> authorization) {
            String offset = "proxy-authorization: digest ";
            String authstring = authorization.orElse("");
            if (!authstring.toLowerCase(Locale.US).startsWith(offset)) {
                return "Proxy-Authenticate: " +
                        "Digest realm=\"" + authenticator.getRealm() + "\","
                        + "\r\n    qop=\"auth\","
                        + "\r\n    nonce=\"" + ns +"\"";
            }
            authstring = authstring
                    .substring(offset.length())
                    .trim();
            boolean validated = false;
            try {
                DigestResponse dgr = DigestResponse.create(authstring);
                validated = validate("CONNECT", dgr);
            } catch (Throwable t) {
                t.printStackTrace();
            }
            if (!validated) {
                return "Proxy-Authenticate: " +
                        "Digest realm=\"" + authenticator.getRealm() + "\","
                        + "\r\n    qop=\"auth\","
                        + "\r\n    nonce=\"" + ns +"\"";
            }
            return null;
        }




        boolean validate(String reqMethod, DigestResponse dg) {
            String type = now() + this.getClass().getSimpleName() + ":" + key;
            if (!"MD5".equalsIgnoreCase(dg.getAlgorithm("MD5"))) {
                System.out.println(type + ": Unsupported algorithm "
                        + dg.algorithm);
                return false;
            }
            if (!"auth".equalsIgnoreCase(dg.getQoP("auth"))) {
                System.out.println(type + ": Unsupported qop "
                        + dg.qop);
                return false;
            }
            try {
                if (!dg.nonce.equals(ns)) {
                    System.out.println(type + ": bad nonce returned by client: "
                            + nonce + " expected " + ns);
                    return false;
                }
                if (dg.response == null) {
                    System.out.println(type + ": missing digest response.");
                    return false;
                }
                char[] pa = authenticator.getPassword(dg.username);
                return verify(type, reqMethod, dg, pa);
            } catch(IllegalArgumentException | SecurityException
                    | NoSuchAlgorithmException e) {
                System.out.println(type + ": " + e.getMessage());
                return false;
            }
        }


        boolean verify(String type, String reqMethod, DigestResponse dg, char[] pw)
                throws NoSuchAlgorithmException {
            String response = DigestResponse.computeDigest(true, reqMethod, pw, dg);
            if (!dg.response.equals(response)) {
                System.out.println(type + ": bad response returned by client: "
                        + dg.response + " expected " + response);
                return false;
            } else {
                // A real server would also verify the uri=<request-uri>
                // parameter - but this is just a test...
                System.out.println(type + ": verified response " + response);
            }
            return true;
        }

        public boolean authorize(StringBuilder response, String requestLine, String headers) {
            String message = "<html><body><p>Authorization Failed%s</p></body></html>\r\n";
            if (authenticator == null && schemeType != HttpAuthSchemeType.NONE) {
                message = String.format(message, " No Authenticator Set");
                response.append("HTTP/1.1 407 Proxy Authentication Failed\r\n");
                response.append("Content-Length: ")
                        .append(message.getBytes(StandardCharsets.UTF_8).length)
                        .append("\r\n\r\n");
                response.append(message);
                return false;
            }
            Optional<String> authorization = Stream.of(headers.split("\r\n"))
                    .filter((k) -> k.toLowerCase(Locale.US).startsWith("proxy-authorization:"))
                    .findFirst();
            String authenticate = null;
            switch(schemeType) {
                case BASIC:
                case BASICSERVER:
                    authenticate = doBasic(authorization);
                    break;
                case DIGEST:
                    authenticate = doDigest(authorization);
                    break;
                case NONE:
                    response.append("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
                    return true;
                default:
                    throw new InternalError("Unknown scheme type: " + schemeType);
            }
            if (authenticate != null) {
                message = String.format(message, "");
                response.append("HTTP/1.1 407 Proxy Authentication Required\r\n");
                response.append("Content-Length: ")
                        .append(message.getBytes(StandardCharsets.UTF_8).length)
                        .append("\r\n")
                        .append(authenticate)
                        .append("\r\n\r\n");
                response.append(message);
                return false;
            }
            response.append("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
            return true;
        }
    }

    public interface TunnelingProxy {
        InetSocketAddress getProxyAddress();
        void stop();
    }

    // This is a bit hacky: HttpsProxyTunnel is an HTTPTestServer hidden
    // behind a fake proxy that only understands CONNECT requests.
    // The fake proxy is just a server socket that intercept the
    // CONNECT and then redirect streams to the real server.
    static class HttpsProxyTunnel extends DigestEchoServer
            implements Runnable, TunnelingProxy {

        final ServerSocket ss;
        final CopyOnWriteArrayList<CompletableFuture<Void>> connectionCFs
                = new CopyOnWriteArrayList<>();
        volatile ProxyAuthorization authorization;
        volatile boolean stopped;
        public HttpsProxyTunnel(String key, HttpTestServer server, DigestEchoServer target,
                                HttpTestHandler delegate)
                throws IOException {
            this(key, server, target, delegate, ServerSocketFactory.create());
        }
        private HttpsProxyTunnel(String key, HttpTestServer server, DigestEchoServer target,
                                HttpTestHandler delegate, ServerSocket ss)
                throws IOException {
            super("HttpsProxyTunnel:" + ss.getLocalPort() + ":" + key,
                    server, target, delegate);
            System.out.flush();
            System.err.println("WARNING: HttpsProxyTunnel is an experimental test class");
            this.ss = ss;
            start();
        }

        final void start() throws IOException {
            Thread t = new Thread(this, "ProxyThread");
            t.setDaemon(true);
            t.start();
        }

        @Override
        public Version getServerVersion() {
            // serverImpl is not null when this proxy
            // serves a single server. It will be null
            // if this proxy can serve multiple servers.
            if (serverImpl != null) return serverImpl.getVersion();
            return null;
        }

        @Override
        public void stop() {
            stopped = true;
            if (serverImpl != null) {
                serverImpl.stop();
            }
            if (redirect != null) {
                redirect.stop();
            }
            try {
                ss.close();
            } catch (IOException ex) {
                if (DEBUG) ex.printStackTrace(System.out);
            }
        }


        @Override
        void configureAuthentication(HttpTestContext ctxt,
                                     HttpAuthSchemeType schemeType,
                                     HttpTestAuthenticator auth,
                                     HttpAuthType authType) {
            if (authType == HttpAuthType.PROXY || authType == HttpAuthType.PROXY305) {
                authorization = new ProxyAuthorization(key, schemeType, auth);
            } else {
                super.configureAuthentication(ctxt, schemeType, auth, authType);
            }
        }

        boolean badRequest(StringBuilder response, String hostport, List<String> hosts) {
            String message = null;
            if (hosts.isEmpty()) {
                message = "No host header provided\r\n";
            } else if (hosts.size() > 1) {
                message = "Multiple host headers provided\r\n";
                for (String h : hosts) {
                    message = message + "host: " + h + "\r\n";
                }
            } else {
                String h = hosts.get(0);
                if (!hostport.equalsIgnoreCase(h)
                        && !hostport.equalsIgnoreCase(h + ":80")
                        && !hostport.equalsIgnoreCase(h + ":443")) {
                    message = "Bad host provided: [" + h
                            + "] doesnot match [" + hostport + "]\r\n";
                }
            }
            if (message != null) {
                int length = message.getBytes(StandardCharsets.UTF_8).length;
                response.append("HTTP/1.1 400 BadRequest\r\n")
                        .append("Content-Length: " + length)
                        .append("\r\n\r\n")
                        .append(message);
                return true;
            }

            return false;
        }

        boolean authorize(StringBuilder response, String requestLine, String headers) {
            if (authorization != null) {
                return authorization.authorize(response, requestLine, headers);
            }
            response.append("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
            return true;
        }

        // Pipe the input stream to the output stream.
        private synchronized Thread pipe(InputStream is, OutputStream os, char tag, CompletableFuture<Void> end) {
            return new Thread("TunnelPipe("+tag+")") {
                @Override
                public void run() {
                    try {
                        int len = 0;
                        byte[] buf = new byte[16 * 1024];
                        try {
                            while ((len = is.read(buf)) != -1) {
                                os.write(buf, 0, len);
                                os.flush();
                                // if DEBUG prints a + or a - for each transferred
                                // character.
                                if (DEBUG) System.out.print(String.valueOf(tag).repeat(len));
                            }
                            is.close();
                        } catch (IOException ex) {
                            if (DEBUG || !stopped && len > -1)
                                ex.printStackTrace(System.out);
                            end.completeExceptionally(ex);
                        } finally {
                            try {os.close();} catch (Throwable t) {}
                        }
                    } finally {
                        end.complete(null);
                    }
                }
            };
        }

        @Override
        public InetSocketAddress getAddress() {
            return new InetSocketAddress(InetAddress.getLoopbackAddress(),
                    ss.getLocalPort());
        }
        @Override
        public InetSocketAddress getProxyAddress() {
            return getAddress();
        }
        @Override
        public InetSocketAddress getServerAddress() {
            // serverImpl can be null if this proxy can serve
            // multiple servers.
            if (serverImpl != null) {
                return serverImpl.getAddress();
            }
            return null;
        }


        // This is a bit shaky. It doesn't handle continuation
        // lines, but our client shouldn't send any.
        // Read a line from the input stream, swallowing the final
        // \r\n sequence. Stops at the first \n, doesn't complain
        // if it wasn't preceded by '\r'.
        //
        String readLine(InputStream r) throws IOException {
            StringBuilder b = new StringBuilder();
            int c;
            while ((c = r.read()) != -1) {
                if (c == '\n') break;
                b.appendCodePoint(c);
            }
            if (b.codePointAt(b.length() -1) == '\r') {
                b.delete(b.length() -1, b.length());
            }
            return b.toString();
        }

        @Override
        public void run() {
            Socket clientConnection = null;
            Socket targetConnection = null;
            try {
                while (!stopped) {
                    System.out.println(now() + "Tunnel: Waiting for client");
                    Socket toClose;
                    targetConnection = clientConnection = null;
                    try {
                        toClose = clientConnection = ss.accept();
                        if (NO_LINGER) {
                            // can be useful to trigger "Connection reset by peer"
                            // errors on the client side.
                            clientConnection.setOption(StandardSocketOptions.SO_LINGER, 0);
                        }
                    } catch (IOException io) {
                        if (DEBUG || !stopped) io.printStackTrace(System.out);
                        break;
                    }
                    System.out.println(now() + "Tunnel: Client accepted");
                    StringBuilder headers = new StringBuilder();
                    InputStream  ccis = clientConnection.getInputStream();
                    OutputStream ccos = clientConnection.getOutputStream();
                    Writer w = new OutputStreamWriter(
                                   clientConnection.getOutputStream(), "UTF-8");
                    PrintWriter pw = new PrintWriter(w);
                    System.out.println(now() + "Tunnel: Reading request line");
                    String requestLine = readLine(ccis);
                    System.out.println(now() + "Tunnel: Request line: " + requestLine);
                    if (requestLine.startsWith("CONNECT ")) {
                        // We should probably check that the next word following
                        // CONNECT is the host:port of our HTTPS serverImpl.
                        // Some improvement for a followup!
                        StringTokenizer tokenizer = new StringTokenizer(requestLine);
                        String connect = tokenizer.nextToken();
                        assert connect.equalsIgnoreCase("connect");
                        String hostport = tokenizer.nextToken();
                        InetSocketAddress targetAddress;
                        List<String> hosts = new ArrayList<>();
                        try {
                            URI uri = new URI("https", hostport, "/", null, null);
                            int port = uri.getPort();
                            port = port == -1 ? 443 : port;
                            targetAddress = new InetSocketAddress(uri.getHost(), port);
                            if (serverImpl != null) {
                                assert targetAddress.getHostString()
                                        .equalsIgnoreCase(serverImpl.getAddress().getHostString());
                                assert targetAddress.getPort() == serverImpl.getAddress().getPort();
                            }
                        } catch (Throwable x) {
                            System.err.printf("Bad target address: \"%s\" in \"%s\"%n",
                                    hostport, requestLine);
                            toClose.close();
                            continue;
                        }

                        // Read all headers until we find the empty line that
                        // signals the end of all headers.
                        String line = requestLine;
                        while(!line.equals("")) {
                            System.out.println(now() + "Tunnel: Reading header: "
                                               + (line = readLine(ccis)));
                            headers.append(line).append("\r\n");
                            int index = line.indexOf(':');
                            if (index >= 0) {
                                String key = line.substring(0, index).trim();
                                if (key.equalsIgnoreCase("host")) {
                                    hosts.add(line.substring(index+1).trim());
                                }
                            }
                        }
                        StringBuilder response = new StringBuilder();
                        if (TUNNEL_REQUIRES_HOST) {
                            if (badRequest(response, hostport, hosts)) {
                                System.out.println(now() + "Tunnel: Sending " + response);
                                // send the 400 response
                                pw.print(response.toString());
                                pw.flush();
                                toClose.close();
                                continue;
                            } else {
                                assert hosts.size() == 1;
                                System.out.println(now()
                                        + "Tunnel: Host header verified " + hosts);
                            }
                        }

                        final boolean authorize = authorize(response, requestLine, headers.toString());
                        if (!authorize) {
                            System.out.println(now() + "Tunnel: Sending "
                                    + response);
                            // send the 407 response
                            pw.print(response.toString());
                            pw.flush();
                            toClose.close();
                            continue;
                        }
                        System.out.println(now()
                                + "Tunnel connecting to target server at "
                                + targetAddress.getAddress() + ":" + targetAddress.getPort());
                        targetConnection = new Socket(
                                targetAddress.getAddress(),
                                targetAddress.getPort());

                        // Then send the 200 OK response to the client
                        System.out.println(now() + "Tunnel: Sending "
                                           + response);
                        pw.print(response);
                        pw.flush();
                    } else {
                        // This should not happen. If it does then just print an
                        // error - both on out and err, and close the accepted
                        // socket
                        System.out.println("WARNING: Tunnel: Unexpected status line: "
                                + requestLine + " received by "
                                + ss.getLocalSocketAddress()
                                + " from "
                                + toClose.getRemoteSocketAddress()
                                + " - closing accepted socket");
                        // Print on err
                        System.err.println("WARNING: Tunnel: Unexpected status line: "
                                             + requestLine + " received by "
                                           + ss.getLocalSocketAddress()
                                           + " from "
                                           + toClose.getRemoteSocketAddress());
                        // close accepted socket.
                        toClose.close();
                        System.err.println("Tunnel: accepted socket closed.");
                        continue;
                    }

                    // Pipe the input stream of the client connection to the
                    // output stream of the target connection and conversely.
                    // Now the client and target will just talk to each other.
                    System.out.println(now() + "Tunnel: Starting tunnel pipes");
                    CompletableFuture<Void> end, end1, end2;
                    Thread t1 = pipe(ccis, targetConnection.getOutputStream(), '+',
                            end1 = new CompletableFuture<>());
                    Thread t2 = pipe(targetConnection.getInputStream(), ccos, '-',
                            end2 = new CompletableFuture<>());
                    var end11 = end1.whenComplete((r, t) -> exceptionally(end2, t));
                    var end22 = end2.whenComplete((r, t) ->  exceptionally(end1, t));
                    end = CompletableFuture.allOf(end11, end22);
                    Socket tc = targetConnection;
                    end.whenComplete(
                            (r,t) -> {
                                try { toClose.close(); } catch (IOException x) { }
                                try { tc.close(); } catch (IOException x) { }
                                finally {connectionCFs.remove(end);}
                            });
                    connectionCFs.add(end);
                    targetConnection = clientConnection = null;
                    t1.start();
                    t2.start();
                }
            } catch (Throwable ex) {
                close(clientConnection, ex);
                close(targetConnection, ex);
                close(ss, ex);
                ex.printStackTrace(System.err);
            } finally {
                System.out.println(now() + "Tunnel: exiting (stopped=" + stopped + ")");
                connectionCFs.forEach(cf -> cf.complete(null));
            }
        }

        void exceptionally(CompletableFuture<?> cf, Throwable t) {
            if (t != null) cf.completeExceptionally(t);
        }

        void close(Closeable c, Throwable e) {
            if (c == null) return;
            try {
                c.close();
            } catch (IOException x) {
                e.addSuppressed(x);
            }
        }
    }

    /**
     * Creates a TunnelingProxy that can serve multiple servers.
     * The server address is extracted from the CONNECT request line.
     * @param authScheme The authentication scheme supported by the proxy.
     *                   Typically one of DIGEST, BASIC, NONE.
     * @return A new TunnelingProxy able to serve multiple servers.
     * @throws IOException If the proxy could not be created.
     */
    public static TunnelingProxy createHttpsProxyTunnel(HttpAuthSchemeType authScheme)
            throws IOException {
        HttpsProxyTunnel result = new HttpsProxyTunnel("", null, null, null);
        if (authScheme != HttpAuthSchemeType.NONE) {
            result.configureAuthentication(null,
                                           authScheme,
                                           AUTHENTICATOR,
                                           HttpAuthType.PROXY);
        }
        return result;
    }

    private static String protocol(String protocol) {
        if ("http".equalsIgnoreCase(protocol)) return "http";
        else if ("https".equalsIgnoreCase(protocol)) return "https";
        else throw new InternalError("Unsupported protocol: " + protocol);
    }

    public static URL url(String protocol, InetSocketAddress address,
                          String path) throws MalformedURLException {
        return new URL(protocol(protocol),
                address.getHostString(),
                address.getPort(), path);
    }

    public static URI uri(String protocol, InetSocketAddress address,
                          String path) throws URISyntaxException {
        return new URI(protocol(protocol) + "://" +
                address.getHostString() + ":" +
                address.getPort() + path);
    }
}
