1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* lib/resolv.rb: fix [ruby-core:28144].

(Resolv::DNS#make_requester): pass nameserver_port to
  UnconnectedUDP.new.
  (Resolv::DNS.bind_random_port): change the is_ipv6 argument to
  bind_host.
  (Resolv::DNS::Requester#initialize): change instance variable to
  store multiple sockets.
  (Resolv::DNS::Requester#request): pass readable sockets to
  recv_reply.
  (Resolv::DNS::Requester#close): close all sockets.
  (Resolv::DNS::Requester::UnconnectedUDP#initialize): allocate
  a socket for each address family of name servers.
  (Resolv::DNS::Requester::UnconnectedUDP#recv_reply): read from the
  passwd readable socket.
  (Resolv::DNS::Requester::UnconnectedUDP#sender): use appropriate
  socket for the target nameserver.
  (Resolv::DNS::Requester::ConnectedUDP): follow the instance variable
  change.
  (Resolv::DNS::Requester::TCP#sender): ditto.
  (Resolv::DNS::Config#nameserver_port): new method.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26637 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2010-02-11 01:29:38 +00:00
parent 9f782768ab
commit d3004ccff3
2 changed files with 82 additions and 33 deletions

View file

@ -1,3 +1,26 @@
Thu Feb 11 09:49:31 2010 Tanaka Akira <akr@fsij.org>
* lib/resolv.rb: fix [ruby-core:28144].
(Resolv::DNS#make_requester): pass nameserver_port to
UnconnectedUDP.new.
(Resolv::DNS.bind_random_port): change the is_ipv6 argument to
bind_host.
(Resolv::DNS::Requester#initialize): change instance variable to
store multiple sockets.
(Resolv::DNS::Requester#request): pass readable sockets to
recv_reply.
(Resolv::DNS::Requester#close): close all sockets.
(Resolv::DNS::Requester::UnconnectedUDP#initialize): allocate
a socket for each address family of name servers.
(Resolv::DNS::Requester::UnconnectedUDP#recv_reply): read from the
passwd readable socket.
(Resolv::DNS::Requester::UnconnectedUDP#sender): use appropriate
socket for the target nameserver.
(Resolv::DNS::Requester::ConnectedUDP): follow the instance variable
change.
(Resolv::DNS::Requester::TCP#sender): ditto.
(Resolv::DNS::Config#nameserver_port): new method.
Thu Feb 11 01:45:04 2010 Yusuke Endoh <mame@tsg.ne.jp> Thu Feb 11 01:45:04 2010 Yusuke Endoh <mame@tsg.ne.jp>
* vm.c (vm_exec): temporarily revert r26628, which causes SEGV when * vm.c (vm_exec): temporarily revert r26628, which causes SEGV when

View file

@ -520,10 +520,11 @@ class Resolv
end end
def make_requester # :nodoc: def make_requester # :nodoc:
if nameserver_port = @config.single? nameserver_port = @config.nameserver_port
Requester::ConnectedUDP.new(*nameserver_port) if nameserver_port.length == 1
Requester::ConnectedUDP.new(*nameserver_port[0])
else else
Requester::UnconnectedUDP.new Requester::UnconnectedUDP.new(*nameserver_port)
end end
end end
@ -609,10 +610,10 @@ class Resolv
} }
end end
def self.bind_random_port(udpsock, is_ipv6=false) # :nodoc: def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
begin begin
port = rangerand(1024..65535) port = rangerand(1024..65535)
udpsock.bind(is_ipv6 ? "::" : "", port) udpsock.bind(bind_host, port)
rescue Errno::EADDRINUSE rescue Errno::EADDRINUSE
retry retry
end end
@ -621,7 +622,7 @@ class Resolv
class Requester # :nodoc: class Requester # :nodoc:
def initialize def initialize
@senders = {} @senders = {}
@sock = nil @socks = nil
end end
def request(sender, tout) def request(sender, tout)
@ -629,10 +630,11 @@ class Resolv
sender.send sender.send
while (now = Time.now) < timelimit while (now = Time.now) < timelimit
timeout = timelimit - now timeout = timelimit - now
if !IO.select([@sock], nil, nil, timeout) select_result = IO.select(@socks, nil, nil, timeout)
if !select_result
raise ResolvTimeout raise ResolvTimeout
end end
reply, from = recv_reply reply, from = recv_reply(select_result[0])
begin begin
msg = Message.decode(reply) msg = Message.decode(reply)
rescue DecodeError rescue DecodeError
@ -648,9 +650,11 @@ class Resolv
end end
def close def close
sock = @sock socks = @socks
@sock = nil @socks = nil
sock.close if sock if socks
socks.each {|sock| sock.close }
end
end end
class Sender # :nodoc: class Sender # :nodoc:
@ -662,16 +666,31 @@ class Resolv
end end
class UnconnectedUDP < Requester # :nodoc: class UnconnectedUDP < Requester # :nodoc:
def initialize def initialize(*nameserver_port)
super() super()
@sock = UDPSocket.new @nameserver_port = nameserver_port
@sock.do_not_reverse_lookup = true @socks_hash = {}
@sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD @socks = []
DNS.bind_random_port(@sock) nameserver_port.each {|host, port|
if host.index(':')
bind_host = "::"
af = Socket::AF_INET6
else
bind_host = "0.0.0.0"
af = Socket::AF_INET
end
next if @socks_hash[bind_host]
sock = UDPSocket.new(af)
sock.do_not_reverse_lookup = true
sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
DNS.bind_random_port(sock, bind_host)
@socks << sock
@socks_hash[bind_host] = sock
}
end end
def recv_reply def recv_reply(readable_socks)
reply, from = @sock.recvfrom(UDPSize) reply, from = readable_socks[0].recvfrom(UDPSize)
return reply, [from[3],from[1]] return reply, [from[3],from[1]]
end end
@ -680,8 +699,9 @@ class Resolv
id = DNS.allocate_request_id(host, port) id = DNS.allocate_request_id(host, port)
request = msg.encode request = msg.encode
request[0,2] = [id].pack('n') request[0,2] = [id].pack('n')
sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
return @senders[[service, id]] = return @senders[[service, id]] =
Sender.new(request, data, @sock, host, port) Sender.new(request, data, sock, host, port)
end end
def close def close
@ -711,15 +731,16 @@ class Resolv
@host = host @host = host
@port = port @port = port
is_ipv6 = host.index(':') is_ipv6 = host.index(':')
@sock = UDPSocket.new(is_ipv6 ? Socket::AF_INET6 : Socket::AF_INET) sock = UDPSocket.new(is_ipv6 ? Socket::AF_INET6 : Socket::AF_INET)
@sock.do_not_reverse_lookup = true @socks = [sock]
@sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD sock.do_not_reverse_lookup = true
DNS.bind_random_port(@sock, is_ipv6) sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
@sock.connect(host, port) DNS.bind_random_port(sock, is_ipv6 ? "::" : "0.0.0.0")
sock.connect(host, port)
end end
def recv_reply def recv_reply(readable_socks)
reply = @sock.recv(UDPSize) reply = readable_socks[0].recv(UDPSize)
return reply, nil return reply, nil
end end
@ -730,7 +751,7 @@ class Resolv
id = DNS.allocate_request_id(@host, @port) id = DNS.allocate_request_id(@host, @port)
request = msg.encode request = msg.encode
request[0,2] = [id].pack('n') request[0,2] = [id].pack('n')
return @senders[[nil,id]] = Sender.new(request, data, @sock) return @senders[[nil,id]] = Sender.new(request, data, @socks[0])
end end
def close def close
@ -753,14 +774,15 @@ class Resolv
super() super()
@host = host @host = host
@port = port @port = port
@sock = TCPSocket.new(@host, @port) sock = TCPSocket.new(@host, @port)
@sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD @socks = [sock]
sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
@senders = {} @senders = {}
end end
def recv_reply def recv_reply(readable_socks)
len = @sock.read(2).unpack('n')[0] len = readable_socks[0].read(2).unpack('n')[0]
reply = @sock.read(len) reply = @socks[0].read(len)
return reply, nil return reply, nil
end end
@ -771,7 +793,7 @@ class Resolv
id = DNS.allocate_request_id(@host, @port) id = DNS.allocate_request_id(@host, @port)
request = msg.encode request = msg.encode
request[0,2] = [request.length, id].pack('nn') request[0,2] = [request.length, id].pack('nn')
return @senders[[nil,id]] = Sender.new(request, data, @sock) return @senders[[nil,id]] = Sender.new(request, data, @socks[0])
end end
class Sender < Requester::Sender # :nodoc: class Sender < Requester::Sender # :nodoc:
@ -932,6 +954,10 @@ class Resolv
end end
end end
def nameserver_port
@nameserver_port
end
def generate_candidates(name) def generate_candidates(name)
candidates = nil candidates = nil
name = Name.create(name) name = Name.create(name)