docs: public List<IncomingPacket> read() {
      // We record the start time to avoid spending too much time on readings
      long startOfCycle = System.nanoTime();
      long bytesRead = 0;
  
      long nPacketsRead = 0;
  
      List<IncomingPacket> ret = new ArrayList<IncomingPacket>();
  
      // We would stop reading when:
      // 1. We spent too much time
      // 2. We have read large enough data
      while ((System.nanoTime() - startOfCycle - readReadBatchTime.toNanos()) < 0
          && (bytesRead < readBatchSize.asBytes())) {
        int readState = incomingPacket.readFromChannel(socketChannel, maximumPacketSize.asBytes());
  
        if (readState > 0) {
          // Partial Read, just break, and read next time when the socket is readable
          break;
        } else if (readState < 0) {
          LOG.severe("Something bad happened while reading from channel: "
              + socketChannel.socket().getRemoteSocketAddress());
          selectHandler.handleError(socketChannel);
  
          // Clear the list of Incoming Packet to avoid bad state is used externally
          ret.clear();
          break;
        } else {
          // readState == 0, we fully read a incomingPacket
          nPacketsRead++;
          bytesRead += incomingPacket.size();
          ret.add(incomingPacket);
          incomingPacket = new IncomingPacket();
        }
      }
  
      totalPacketsRead += nPacketsRead;
      totalBytesRead += bytesRead;
  
      return ret;
    }