docs: protected VirtualConnection startResponseRead() {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.entry(tc, "startResponseRead");
          }
          HttpInvalidMessageException inv = checkRequestValidity();
          if (null != inv) {
              getAppWriteCallback().error(getVC(), inv);
              if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
                  Tr.exit(tc, "startResponseRead: error");
              }
              return null;
          }
          // check whether read-ahead is enabled. Bypass this code once the
          // init() method has been called (d264854) and continue as normal
          if (isReadAheadEnabled() && READ_STATE_TIME_RESET != getReadState()) {
              // read ahead is active
  
              int state = CALLBACK_STATE_IDLE;
              // grab the read-ahead states in a sync block to avoid timing windows
              // with the callback kicking in at the same time
              synchronized (this.stateSyncObject) {
                  state = getCallbackState();
                  setReadState(READ_STATE_ASYNC);
              }
  
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "Async response read, callback state: " + state);
              }
              switch (state) {
                  case (CALLBACK_STATE_COMPLETE):
                      // read-ahead has already completed successfully, start the
                      // parse logic now
                      readAsyncResponse();
                      break;
                  case (CALLBACK_STATE_ERROR):
                      // read-ahead already hit an error, trigger that path now
                      setPersistent(false);
                      reConnect(getVC(), this.readException);
                      break;
                  case (CALLBACK_STATE_PENDING):
                      // read-ahead is still going on
                      break;
                  default:
                      if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                          Tr.debug(tc, "Unexpected state (" + state + ") during async readahead");
                      }
                      setPersistent(false);
                      reConnect(getVC(), new IOException("Read-ahead state failure"));
                      break;
              }
              if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
                  Tr.exit(tc, "startResponseRead: read-ahead");
              }
              return null;
          }
  
          // When we get here, then the final write of the request has finished
          // and we need to tell the app channel of that IF the temp response
          // reads have been triggered. We will not read for a response here as
          // the app channel is using readNextResponse() for that path.
          // LI4335 - early reads also avoid starting read here
          if (this.bEarlyReads || this.bTempResponsesUsed) {
              if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
                  Tr.exit(tc, "startResponseRead: temp resp env");
              }
              getAppWriteCallback().complete(getVC());
              return null;
          }
  
          // otherwise start the read for the response now...
          getResponseImpl();
          readAsyncResponse();
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.exit(tc, "startResponseRead");
          }
          return null;
      }