docs: protected void determineNextChannel() {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.entry(tc, "determineNextChannel, vc=" + getVCHash());
          }
  
          // Pass the buffers up to the application side channel.
          ConnectionReadyCallback linkOnApplicationSide = getApplicationCallback();
          if (linkOnApplicationSide != null) {
              linkOnApplicationSide.ready(getVirtualConnection());
          } else {
              int discriminationResult = Discriminator.YES;
              try {
                  // Need to go all the way back to the SSL channel to get the
                  // latest disc process in case it has changed.
                  discriminationResult = getChannel().getDiscriminationProcess().discriminate(getVirtualConnection(), readInterface.getBuffers(), this);
              } catch (Exception e) {
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                      Tr.debug(tc, "Exception caught doing discriminate, " + e);
                  }
                  FFDCFilter.processException(e, getClass().getName(), "346", this);
                  throw new RuntimeException("Exception caught doing discriminate, " + e);
              }
  
              switch (discriminationResult) {
                  case DiscriminationProcess.SUCCESS: {
                      // Call the next channel, assigned during discrimination.
                      getApplicationCallback().ready(getVirtualConnection());
                      break;
                  }
                  case DiscriminationProcess.FAILURE: {
                      // No next channel will be called. Therefore, read interface buffers must be freed here.
                      WsByteBuffer[] buffers = getDeviceReadInterface().getBuffers();
                      // clear out the readInterface buffer so that we only close (release) it once
                      for (int i = 0; i < buffers.length; i++) {
                          if (buffers[i] == readInterface.netBuffer) {
                              buffers[i] = null;
                          }
                      }
                      WsByteBufferUtils.releaseBufferArray(buffers);
                      // Close down the vc with an exception
                      close(getVirtualConnection(), new Exception("Failure response from discrimination process."));
                      break;
                  }
                  case DiscriminationProcess.AGAIN: {
                      // TODO: this doesn't set up for a read...
                      // Need to read more in order to determine next channel. ForceQueue is true.
                      readInterface.setBuffer(readInterface.getBuffer());
                      // The read will be asynchronous so a callback is needed.
                      MoreDataNeededCallback callback = new MoreDataNeededCallback();
                      // No need to save number of bytes read. If problem occurs here, IOException is thrown.
                      // Do the asychronous read. Forcequeue is false, so the callback may not be necessary.
                      if (null != readInterface.read(1, callback, false, TCPRequestContext.USE_CHANNEL_TIMEOUT)) {
                          // Data is ready. The callback will not be called.
                          // Recursively call this method to determine the next channel.
                          determineNextChannel();
                      }
                      break;
                  }
                  default: {
                      // No next channel will be called. Therefore, read interface buffers must be freed here.
                      WsByteBufferUtils.releaseBufferArray(getDeviceReadInterface().getBuffers());
                      // Close down the vc with an exception
                      close(getVirtualConnection(), new Exception("Unknown response from discrimination process, " + discriminationResult));
                      break;
                  }
              }
          }
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.exit(tc, "determineNextChannel");
          }
      }