class Excon::Socket

def read(max_length=nil)

def read(max_length=nil)
  if @eof
    return max_length ? nil : ''
  elsif @nonblock
    begin
      if max_length
        until @read_buffer.length >= max_length
          @read_buffer << @socket.read_nonblock(max_length - @read_buffer.length)
        end
      else
        while true
          @read_buffer << @socket.read_nonblock(@data[:chunk_size])
        end
      end
    rescue OpenSSL::SSL::SSLError => error
      if error.message == 'read would block'
        if IO.select([@socket], nil, nil, @data[:read_timeout])
          retry
        else
          raise(Excon::Errors::Timeout.new("read timeout reached"))
        end
      else
        raise(error)
      end
    rescue Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable
      if IO.select([@socket], nil, nil, @data[:read_timeout])
        retry
      else
        raise(Excon::Errors::Timeout.new("read timeout reached"))
      end
    rescue EOFError
      @eof = true
    end
    if max_length
      if @read_buffer.empty?
        nil # EOF met at beginning
      else
        @read_buffer.slice!(0, max_length)
      end
    else
      # read until EOFError, so return everything
      @read_buffer.slice!(0, @read_buffer.length)
    end
  else
    begin
      Timeout.timeout(@data[:read_timeout]) do
        @socket.read(max_length)
      end
    rescue Timeout::Error
      raise Excon::Errors::Timeout.new('read timeout reached')
    end
  end
end