class Excon::Socket

def read_nonblock(max_length)

def read_nonblock(max_length)
  begin
    if @read_offset != 0 && @read_offset >= @read_buffer.length
      # Clear the buffer so we can test for emptiness below
      @read_buffer.clear
      # Reset the offset so it matches the length of the buffer when empty.
      @read_offset = 0
    end
    if max_length
      until @backend_eof || readable_bytes >= max_length
        if @read_buffer.empty?
          # Avoid allocating a new buffer string when the read buffer is empty
          @read_buffer = @socket.read_nonblock(max_length, @read_buffer)
        else
          @read_buffer << @socket.read_nonblock(max_length - readable_bytes)
        end
      end
    else
      until @backend_eof
        if @read_buffer.empty?
          # Avoid allocating a new buffer string when the read buffer is empty
          @read_buffer = @socket.read_nonblock(@data[:chunk_size], @read_buffer)
        else
          @read_buffer << @socket.read_nonblock(@data[:chunk_size])
        end
      end
    end
  rescue OpenSSL::SSL::SSLError => error
    if error.message == 'read would block'
      if @read_buffer.empty?
        select_with_timeout(@socket, :read) && retry
      end
    else
      raise(error)
    end
  rescue *READ_RETRY_EXCEPTION_CLASSES
    if @read_buffer.empty?
      # if we didn't read anything, try again...
      select_with_timeout(@socket, :read) && retry
    end
  rescue EOFError
    @backend_eof = true
  end
  if max_length
    if @read_buffer.empty?
      # EOF met at beginning
      @eof = @backend_eof
      nil
    else
      start = @read_offset
      # Ensure that we can seek backwards when reading until a terminator string.
      # The read offset must never point past the end of the read buffer.
      @read_offset += max_length > readable_bytes ? readable_bytes : max_length
      @read_buffer[start...@read_offset]
    end
  else
    # read until EOFError, so return everything
    start = @read_offset
    @read_offset = @read_buffer.length
    @eof = @backend_eof
    @read_buffer[start..-1]
  end
end