docs: public static <I extends StreamSourceChannel, O extends StreamSinkChannel> void initiateTransfer(final I source, final O sink, final ChannelListener<? super I> sourceListener, final ChannelListener<? super O> sinkListener, final ChannelExceptionHandler<? super I> readExceptionHandler, final ChannelExceptionHandler<? super O> writeExceptionHandler, ByteBufferPool pool) {
          if (pool == null) {
              throw UndertowMessages.MESSAGES.argumentCannotBeNull("pool");
          }
          final PooledByteBuffer allocated = pool.allocate();
          boolean free = true;
          try {
              final ByteBuffer buffer = allocated.getBuffer();
              long read;
              for(;;) {
                  try {
                      read = source.read(buffer);
                      buffer.flip();
                  } catch (IOException e) {
                      ChannelListeners.invokeChannelExceptionHandler(source, readExceptionHandler, e);
                      return;
                  }
                  if (read == 0 && !buffer.hasRemaining()) {
                      break;
                  }
                  if (read == -1 && !buffer.hasRemaining()) {
                      done(source, sink, sourceListener, sinkListener);
                      return;
                  }
                  while (buffer.hasRemaining()) {
                      final int res;
                      try {
                          res = sink.write(buffer);
                      } catch (IOException e) {
                          ChannelListeners.invokeChannelExceptionHandler(sink, writeExceptionHandler, e);
                          return;
                      }
                      if (res == 0) {
                          break;
                      }
                  }
                  if(buffer.hasRemaining()) {
                      break;
                  }
                  buffer.clear();
              }
              PooledByteBuffer current = null;
              if(buffer.hasRemaining()) {
                  current = allocated;
                  free = false;
              }
  
              final TransferListener<I, O> listener = new TransferListener<I, O>(pool, current, source, sink, sourceListener, sinkListener, writeExceptionHandler, readExceptionHandler, read == -1);
              sink.getWriteSetter().set(listener);
              source.getReadSetter().set(listener);
              //we resume both reads and writes, as we want to keep trying to fill the buffer
              if(current == null || buffer.capacity() != buffer.remaining()) {
                  //we don't resume if the buffer is 100% full
                  source.resumeReads();
              }
              if(current != null) {
                  //we don't resume writes if we have nothing to write
                  sink.resumeWrites();
              }
          } finally {
              if (free) {
                  allocated.close();
              }
          }
      }