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
|
| Defined in: | lib/resolv.rb |
Class Method Summary
- .new(host, port = Port) ⇒ TCP constructor
Instance Attribute Summary
- #reusable? ⇒ Boolean readonly
Instance Method Summary
- #close
- #recv_reply(readable_socks, timelimit = nil)
- #sender(msg, data, host = @host, port = @port)
-
#read_exactly(sock, len, timelimit)
private
Read
lenbytes, giving up with::Resolv::ResolvTimeoutoncetimelimit(a CLOCK_MONOTONIC value) has passed.
Constructor Details
.new(host, port = Port) ⇒ TCP
# 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.
# 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