gt:                 int count = in.read(response, total, response.length - total);
context: /*
   * Copyright (c) 2015, 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 8046321
   * @summary OCSP Stapling for TLS
   * @library ../../../../java/security/testlibrary
   * @build CertificateBuilder SimpleOCSPServer
   * @run main/othervm HttpsUrlConnClient
   */
  
  import java.io.*;
  import java.math.BigInteger;
  import java.security.KeyPair;
  import java.security.KeyPairGenerator;
  import java.net.Socket;
  import java.net.URL;
  import java.net.HttpURLConnection;
  import java.net.InetAddress;
  import javax.net.ssl.*;
  import java.security.KeyStore;
  import java.security.PublicKey;
  import java.security.Security;
  import java.security.GeneralSecurityException;
  import java.security.cert.CertPathValidatorException;
  import java.security.cert.CertPathValidatorException.BasicReason;
  import java.security.cert.Certificate;
  import java.security.cert.PKIXBuilderParameters;
  import java.security.cert.X509CertSelector;
  import java.security.cert.X509Certificate;
  import java.security.cert.PKIXRevocationChecker;
  import java.security.spec.PKCS8EncodedKeySpec;
  import java.text.SimpleDateFormat;
  import java.util.*;
  import java.util.concurrent.TimeUnit;
  
  import sun.security.testlibrary.SimpleOCSPServer;
  import sun.security.testlibrary.CertificateBuilder;
  import sun.security.validator.ValidatorException;
  
  public class HttpsUrlConnClient {
  
      /*
       * =============================================================
       * Set the various variables needed for the tests, then
       * specify what tests to run on each side.
       */
  
      static final byte[] LINESEP = { 10 };
      static final Base64.Encoder B64E = Base64.getMimeEncoder(64, LINESEP);
  
      // Turn on TLS debugging
      static boolean debug = true;
  
      /*
       * Should we run the client or server in a separate thread?
       * Both sides can throw exceptions, but do you have a preference
       * as to which side should be the main thread.
       */
      static boolean separateServerThread = true;
      Thread clientThread = null;
      Thread serverThread = null;
  
      static String passwd = "passphrase";
      static String ROOT_ALIAS = "root";
      static String INT_ALIAS = "intermediate";
      static String SSL_ALIAS = "ssl";
  
      /*
       * Is the server ready to serve?
       */
      volatile static boolean serverReady = false;
      volatile int serverPort = 0;
  
      volatile Exception serverException = null;
      volatile Exception clientException = null;
  
      // PKI components we will need for this test
      static KeyStore rootKeystore;           // Root CA Keystore
      static KeyStore intKeystore;            // Intermediate CA Keystore
      static KeyStore serverKeystore;         // SSL Server Keystore
      static KeyStore trustStore;             // SSL Client trust store
      static SimpleOCSPServer rootOcsp;       // Root CA OCSP Responder
      static int rootOcspPort;                // Port number for root OCSP
      static SimpleOCSPServer intOcsp;        // Intermediate CA OCSP Responder
      static int intOcspPort;                 // Port number for intermed. OCSP
  
      private static final String SIMPLE_WEB_PAGE = "<HTML>\n" +
              "<HEAD><Title>Web Page!</Title></HEAD>\n" +
              "<BODY><H1>Web Page!</H1></BODY>\n</HTML>";
      private static final SimpleDateFormat utcDateFmt =
              new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z");
      /*
       * If the client or server is doing some kind of object creation
       * that the other side depends on, and that thread prematurely
       * exits, you may experience a hang.  The test harness will
       * terminate all hung threads after its timeout has expired,
       * currently 3 minutes by default, but you might try to be
       * smart about it....
       */
      public static void main(String[] args) throws Exception {
          if (debug) {
              System.setProperty("javax.net.debug", "ssl");
          }
  
          System.setProperty("javax.net.ssl.keyStore", "");
          System.setProperty("javax.net.ssl.keyStorePassword", "");
          System.setProperty("javax.net.ssl.trustStore", "");
          System.setProperty("javax.net.ssl.trustStorePassword", "");
  
          // Create the PKI we will use for the test and start the OCSP servers
          createPKI();
          utcDateFmt.setTimeZone(TimeZone.getTimeZone("GMT"));
  
          testPKIXParametersRevEnabled();
  
          // shut down the OCSP responders before finishing the test
          intOcsp.stop();
          rootOcsp.stop();
      }
  
      /**
       * Do a basic connection using PKIXParameters with revocation checking
       * enabled and client-side OCSP disabled.  It will only pass if all
       * stapled responses are present, valid and have a GOOD status.
       */
      static void testPKIXParametersRevEnabled() throws Exception {
          ClientParameters cliParams = new ClientParameters();
          ServerParameters servParams = new ServerParameters();
          serverReady = false;
  
          System.out.println("=====================================");
          System.out.println("Stapling enabled, PKIXParameters with");
          System.out.println("Revocation checking enabled ");
          System.out.println("=====================================");
  
          // Set the certificate entry in the intermediate OCSP responder
          // with a revocation date of 8 hours ago.
          X509Certificate sslCert =
                  (X509Certificate)serverKeystore.getCertificate(SSL_ALIAS);
          Map<BigInteger, SimpleOCSPServer.CertStatusInfo> revInfo =
              new HashMap<>();
          revInfo.put(sslCert.getSerialNumber(),
                  new SimpleOCSPServer.CertStatusInfo(
                          SimpleOCSPServer.CertStatus.CERT_STATUS_REVOKED,
                          new Date(System.currentTimeMillis() -
                                  TimeUnit.HOURS.toMillis(8))));
          intOcsp.updateStatusDb(revInfo);
  
          // Set up revocation checking on the client with no client-side
          // OCSP fall-back
          cliParams.pkixParams = new PKIXBuilderParameters(trustStore,
                  new X509CertSelector());
          cliParams.pkixParams.setRevocationEnabled(true);
          Security.setProperty("ocsp.enable", "false");
  
          HttpsUrlConnClient sslTest = new HttpsUrlConnClient(cliParams,
                  servParams);
          TestResult tr = sslTest.getResult();
          if (!checkClientValidationFailure(tr.clientExc, BasicReason.REVOKED)) {
              if (tr.clientExc != null) {
                  throw tr.clientExc;
              } else {
                  throw new RuntimeException(
                          "Expected client failure, but the client succeeded");
              }
          }
  
          // In this case the server should also have thrown an exception
          // because of the client alert
          if (tr.serverExc instanceof SSLHandshakeException) {
              if (!tr.serverExc.getMessage().contains(
                      "alert: bad_certificate_status_response")) {
                  throw tr.serverExc;
              }
          }
  
          System.out.println("                PASS");
          System.out.println("=====================================\n");
      }
  
      /*
       * Define the server side of the test.
       *
       * If the server prematurely exits, serverReady will be set to true
       * to avoid infinite hangs.
       */
      void doServerSide(ServerParameters servParams) throws Exception {
  
          // Selectively enable or disable the feature
          System.setProperty("jdk.tls.server.enableStatusRequestExtension",
                  Boolean.toString(servParams.enabled));
  
          // Set all the other operating parameters
          System.setProperty("jdk.tls.stapling.cacheSize",
                  Integer.toString(servParams.cacheSize));
          System.setProperty("jdk.tls.stapling.cacheLifetime",
                  Integer.toString(servParams.cacheLifetime));
          System.setProperty("jdk.tls.stapling.responseTimeout",
                  Integer.toString(servParams.respTimeout));
          System.setProperty("jdk.tls.stapling.responderURI", servParams.respUri);
          System.setProperty("jdk.tls.stapling.responderOverride",
                  Boolean.toString(servParams.respOverride));
          System.setProperty("jdk.tls.stapling.ignoreExtensions",
                  Boolean.toString(servParams.ignoreExts));
  
          // Set keystores and trust stores for the server
          KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
          kmf.init(serverKeystore, passwd.toCharArray());
          TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
          tmf.init(trustStore);
  
          SSLContext sslc = SSLContext.getInstance("TLS");
          sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
  
          SSLServerSocketFactory sslssf = sslc.getServerSocketFactory();
          SSLServerSocket sslServerSocket =
              (SSLServerSocket) sslssf.createServerSocket(serverPort);
  
          serverPort = sslServerSocket.getLocalPort();
          log("Server Port is " + serverPort);
  
          // Dump the private key in PKCS8 format, not encrypted.  This
          // key dump can be used if the traffic was captured using tcpdump
          // or wireshark to look into the encrypted packets for debug purposes.
          if (debug) {
              byte[] keybytes = serverKeystore.getKey(SSL_ALIAS,
                      passwd.toCharArray()).getEncoded();
              PKCS8EncodedKeySpec p8spec = new PKCS8EncodedKeySpec(keybytes);
              StringBuilder keyPem = new StringBuilder();
              keyPem.append("-----BEGIN PRIVATE KEY-----\n");
              keyPem.append(B64E.encodeToString(p8spec.getEncoded())).append("\n");
              keyPem.append("-----END PRIVATE KEY-----\n");
              log("Private key is:\n" + keyPem.toString());
          }
  
          /*
           * Signal Client, we're ready for his connect.
           */
          serverReady = true;
  
          try (SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
                  BufferedReader in = new BufferedReader(
                      new InputStreamReader(sslSocket.getInputStream()));
                  OutputStream out = sslSocket.getOutputStream()) {
              StringBuilder hdrBldr = new StringBuilder();
              String line;
              while ((line = in.readLine()) != null && !line.isEmpty()) {
                  hdrBldr.append(line).append("\n");
              }
              String headerText = hdrBldr.toString();
              log("Header Received: " + headerText.length() + " bytes\n" +
                      headerText);
  
              StringBuilder sb = new StringBuilder();
              sb.append("HTTP/1.0 200 OK\r\n");
              sb.append("Date: ").append(utcDateFmt.format(new Date())).
                      append("\r\n");
              sb.append("Content-Type: text/html\r\n");
              sb.append("Content-Length: ").append(SIMPLE_WEB_PAGE.length());
              sb.append("\r\n\r\n");
              out.write(sb.toString().getBytes("UTF-8"));
              out.write(SIMPLE_WEB_PAGE.getBytes("UTF-8"));
              out.flush();
              log("Server replied with:\n" + sb.toString() + SIMPLE_WEB_PAGE);
          }
      }
  
      /*
       * Define the client side of the test.
       *
       * If the server prematurely exits, serverReady will be set to true
       * to avoid infinite hangs.
       */
      void doClientSide(ClientParameters cliParams) throws Exception {
  
          /*
           * Wait for server to get started.
           */
          while (!serverReady) {
              Thread.sleep(50);
          }
  
          // Selectively enable or disable the feature
          System.setProperty("jdk.tls.client.enableStatusRequestExtension",
                  Boolean.toString(cliParams.enabled));
  
          HtucSSLSocketFactory sockFac = new HtucSSLSocketFactory(cliParams);
          HttpsURLConnection.setDefaultSSLSocketFactory(sockFac);
          URL location = new URL("https://localhost:" + serverPort);
          HttpsURLConnection tlsConn =
                  (HttpsURLConnection)location.openConnection();
          tlsConn.setConnectTimeout(5000);
          tlsConn.setReadTimeout(5000);
          tlsConn.setDoInput(true);
  
          try (InputStream in = tlsConn.getInputStream()) {
              // Check the response
              if (debug && tlsConn.getResponseCode() !=
                      HttpURLConnection.HTTP_OK) {
                  log("Received HTTP error: " + tlsConn.getResponseCode() +
                          " - " + tlsConn.getResponseMessage());
                  throw new IOException("HTTP error: " +
                          tlsConn.getResponseCode());
              }
  
              int contentLength = tlsConn.getContentLength();
              if (contentLength == -1) {
                  contentLength = Integer.MAX_VALUE;
              }
              byte[] response = new byte[contentLength > 2048 ? 2048 : contentLength];
              int total = 0;
              while (total < contentLength) {
  