docs: public VirtualConnection encryptAndWriteAsync(long numBytes, boolean forceQueue, int timeout) {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.entry(tc, "encryptAndWriteAsync: " + numBytes);
          }
  
          this.asyncBytesToWrite = 0L;
          this.asyncTimeout = timeout;
          VirtualConnection vc = null;
  
          try {
              long numBytesLeft = numBytes;
              // make sure we have an output buffer of the target size ready
              final int packetSize = getConnLink().getPacketBufferSize();
              if (numBytesLeft > packetSize) {
                  getEncryptedAppBuffer(packetSize * 2);
              } else {
                  getEncryptedAppBuffer(1);
              }
              final int cap = this.encryptedAppBuffer.capacity();
              final TCPWriteRequestContext tcp = getConnLink().getDeviceWriteInterface();
              SSLEngineResult result;
              int produced;
  
              do {
                  this.encryptedAppBuffer.clear();
  
                  result = encryptMessage();
                  numBytesLeft -= result.bytesConsumed();
                  produced = result.bytesProduced();
                  if (0 < produced) {
                      while (0 < numBytesLeft && (cap - produced) >= packetSize) {
                          // space in the current output buffer to encrypt a little more
                          // Note: JSSE requires a full packet size of open space regardless of the input
                          // amount, so even 100 bytes to encrypt requires 16K of output space
                          result = encryptMessage();
                          numBytesLeft -= result.bytesConsumed();
                          produced += result.bytesProduced();
                      }
  
                      // in case this goes async, save bytes-left to pick up later
                      this.asyncBytesToWrite = numBytesLeft;
                      this.encryptedAppBuffer.flip();
                      tcp.setBuffer(this.encryptedAppBuffer);
                      vc = tcp.write(TCPWriteRequestContext.WRITE_ALL_DATA, this, forceQueue, timeout);
                  }
              } while (null != vc && 0 < numBytesLeft && 0 < produced);
  
          } catch (IOException exception) {
              // No FFDC needed. Callback will handle.
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "Caught exception during encryption, " + exception);
              }
              this.callback.error(getConnLink().getVirtualConnection(), this, exception);
          } catch (Exception original) {
              synchronized (closeSync) {
                  // if close has been called then assume this exception was due to a race condition
                  // with the close logic. so no FFDC here.
                  if (closeCalled) {
                      return null;
                  } else {
                      throw original;
                  }
              }
          }
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) {
              Tr.exit(tc, "encryptAndWriteAsync: " + vc);
          }
          return vc;
      }