code: public synchronized int read(byte[] externalBuf, int off, int len) throws IOException {
  
      if (len == 0) {
        return 0;
      }
  
      int totalReads = 0;
      while (true) {
  
        //read
        if (end - pos <= 0) {
          if (len - totalReads >= buf.length) {
            //buffer length is less than asked byte and buffer is empty
            // => filling directly into external buffer
            int reads = super.read(externalBuf, off + totalReads, len - totalReads);
            if (reads <= 0) {
              return (totalReads == 0) ? -1 : totalReads;
            }
            return totalReads + reads;
  
          } else {
  
            //filling internal buffer
            fillBuffer(len - totalReads);
            if (end <= 0) {
              return (totalReads == 0) ? -1 : totalReads;
            }
          }
        }
  
        //copy internal value to buffer.
        int copyLength = Math.min(len - totalReads, end - pos);
        System.arraycopy(buf, pos, externalBuf, off + totalReads, copyLength);
        pos += copyLength;
        totalReads += copyLength;
  
        if (totalReads >= len || super.available() <= 0) {
          return totalReads;
        }
      }
    }
docs: Returing byte array, from cache of reading socket if needed.
  
  @param externalBuf   buffer to fill
  @param off           offset
  @param len           length to read
  @return number of added bytes
  @throws IOException if exception during socket reading