123456789_123456789_123456789_123456789_123456789_

Class: Resolv::DNS::Requester::TCP

Do not use. This class is for internal use only.
Relationships & Source Files
Namespace Children
Classes:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Requester
Instance Chain:
self, Requester
Inherits: Requester
  • Object
Defined in: lib/resolv.rb

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(host, port = Port) ⇒ TCP

[ GitHub ]

  
# File 'lib/resolv.rb', line 949

def initialize(host, port=Port)
  super()
  @host = host
  @port = port
  sock = TCPSocket.new(@host, @port)
  @socks = [sock]
  @senders = {}
  @reusable = true
end

Instance Attribute Details

#reusable?Boolean (readonly)

[ GitHub ]

  
# File 'lib/resolv.rb', line 959

def reusable?
  @reusable
end

Instance Method Details

#close

[ GitHub ]

  
# File 'lib/resolv.rb', line 998

def close
  @reusable = false
  super
  @senders.each_key {|from,id|
    DNS.free_request_id(@host, @port, id)
  }
end

#read_exactly(sock, len, timelimit) (private)

Read len bytes, giving up with ::Resolv::ResolvTimeout once timelimit (a CLOCK_MONOTONIC value) has passed. A shorter result means the peer closed the connection, which the caller turns into an EOFError. Consuming any byte marks the requester unusable until the whole frame has been read, since giving up in between loses frame sync. Without a timelimit the read blocks instead and keeps no such mark; that is only for a caller still using the one argument form of #recv_reply.

[ GitHub ]

  
# File 'lib/resolv.rb', line 1015

def read_exactly(sock, len, timelimit)
  return sock.read(len) unless timelimit
  buf = String.new
  while buf.bytesize < len
    case chunk = sock.read_nonblock(len - buf.bytesize, exception: false)
    when :wait_readable
      remaining = timelimit - Process.clock_gettime(Process::CLOCK_MONOTONIC)
      raise ResolvTimeout if remaining <= 0
      sock.wait_readable(remaining) or raise ResolvTimeout
    when nil
      break
    else
      @reusable = false
      buf << chunk
    end
  end
  buf
end

#recv_reply(readable_socks, timelimit = nil)

[ GitHub ]

  
# File 'lib/resolv.rb', line 963

def recv_reply(readable_socks, timelimit = nil)
  sock = readable_socks[0]
  len_data = read_exactly(sock, 2, timelimit)
  raise EOFError if len_data.nil? || len_data.bytesize != 2
  len = len_data.unpack('n')[0]
  reply = read_exactly(sock, len, timelimit)
  raise EOFError if reply.nil? || reply.bytesize != len
  @reusable = true
  return reply, nil
rescue EOFError, SystemCallError
  # Whatever the kernel reported, this socket cannot be trusted for
  # another frame.  In practice that is the peer closing or resetting;
  # the rest is rare enough that erring towards reconnecting is right.
  @reusable = false
  raise
end

#sender(msg, data, host = @host, port = @port)

[ GitHub ]

  
# File 'lib/resolv.rb', line 980

def sender(msg, data, host=@host, port=@port)
  unless host == @host && port == @port
    raise RequestError.new("host/port don't match: #{host}:#{port}")
  end
  id = DNS.allocate_request_id(@host, @port)
  request = msg.encode
  request[0,2] = [request.length, id].pack('nn')
  return @senders[[nil,id]] = Sender.new(request, data, @socks[0])
end