summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorshyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-05-22 11:55:21 +0000
committershyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-05-22 11:55:21 +0000
commit261a74df83b5e7278d7b3f88bf4258f91988aeee (patch)
tree209400aa0532fbe8c513dc8e98eca924551f725b /lib
parentb6b1a387f1637aae55d9d7636d03db49b46ea75f (diff)
merge revision(s) 26636:26638:
* lib/resolv.rb: fix [ruby-core:28144] reported by Hans de Graaff. (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/branches/ruby_1_8_7@27956 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r--lib/resolv.rb90
1 files changed, 59 insertions, 31 deletions
diff --git a/lib/resolv.rb b/lib/resolv.rb
index 4f0c71cc40..b9a2174191 100644
--- a/lib/resolv.rb
+++ b/lib/resolv.rb
@@ -503,10 +503,11 @@ class Resolv
end
def make_requester # :nodoc:
- if nameserver = @config.single?
- Requester::ConnectedUDP.new(nameserver)
+ nameserver_port = @config.nameserver_port
+ if nameserver_port.length == 1
+ Requester::ConnectedUDP.new(*nameserver_port[0])
else
- Requester::UnconnectedUDP.new
+ Requester::UnconnectedUDP.new(*nameserver_port)
end
end
@@ -592,10 +593,10 @@ class Resolv
}
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
port = rangerand(1024..65535)
- udpsock.bind(is_ipv6 ? "::" : "", port)
+ udpsock.bind(bind_host, port)
rescue Errno::EADDRINUSE
retry
end
@@ -604,7 +605,7 @@ class Resolv
class Requester # :nodoc:
def initialize
@senders = {}
- @sock = nil
+ @socks = nil
end
def request(sender, tout)
@@ -612,10 +613,11 @@ class Resolv
sender.send
while (now = Time.now) < timelimit
timeout = timelimit - now
- if !IO.select([@sock], nil, nil, timeout)
+ select_result = IO.select(@socks, nil, nil, timeout)
+ if !select_result
raise ResolvTimeout
end
- reply, from = recv_reply
+ reply, from = recv_reply(select_result[0])
begin
msg = Message.decode(reply)
rescue DecodeError
@@ -631,9 +633,11 @@ class Resolv
end
def close
- sock = @sock
- @sock = nil
- sock.close if sock
+ socks = @socks
+ @socks = nil
+ if socks
+ socks.each {|sock| sock.close }
+ end
end
class Sender # :nodoc:
@@ -645,15 +649,30 @@ class Resolv
end
class UnconnectedUDP < Requester # :nodoc:
- def initialize
+ def initialize(*nameserver_port)
super()
- @sock = UDPSocket.new
- @sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
- DNS.bind_random_port(@sock)
+ @nameserver_port = nameserver_port
+ @socks_hash = {}
+ @socks = []
+ 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.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
- def recv_reply
- reply, from = @sock.recvfrom(UDPSize)
+ def recv_reply(readable_socks)
+ reply, from = readable_socks[0].recvfrom(UDPSize)
return reply, [from[3],from[1]]
end
@@ -662,8 +681,9 @@ class Resolv
id = DNS.allocate_request_id(host, port)
request = msg.encode
request[0,2] = [id].pack('n')
+ sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
return @senders[[service, id]] =
- Sender.new(request, data, @sock, host, port)
+ Sender.new(request, data, sock, host, port)
end
def close
@@ -693,14 +713,15 @@ class Resolv
@host = host
@port = port
is_ipv6 = host.index(':')
- @sock = UDPSocket.new(is_ipv6 ? Socket::AF_INET6 : Socket::AF_INET)
- DNS.bind_random_port(@sock, is_ipv6)
- @sock.connect(host, port)
- @sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
+ sock = UDPSocket.new(is_ipv6 ? Socket::AF_INET6 : Socket::AF_INET)
+ @socks = [sock]
+ sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
+ DNS.bind_random_port(sock, is_ipv6 ? "::" : "0.0.0.0")
+ sock.connect(host, port)
end
- def recv_reply
- reply = @sock.recv(UDPSize)
+ def recv_reply(readable_socks)
+ reply = readable_socks[0].recv(UDPSize)
return reply, nil
end
@@ -711,7 +732,7 @@ class Resolv
id = DNS.allocate_request_id(@host, @port)
request = msg.encode
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
def close
@@ -734,14 +755,15 @@ class Resolv
super()
@host = host
@port = port
- @sock = TCPSocket.new(@host, @port)
- @sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
+ sock = TCPSocket.new(@host, @port)
+ @socks = [sock]
+ sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
@senders = {}
end
- def recv_reply
- len = @sock.read(2).unpack('n')[0]
- reply = @sock.read(len)
+ def recv_reply(readable_socks)
+ len = readable_socks[0].read(2).unpack('n')[0]
+ reply = @socks[0].read(len)
return reply, nil
end
@@ -752,7 +774,7 @@ class Resolv
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, @sock)
+ return @senders[[nil,id]] = Sender.new(request, data, @socks[0])
end
class Sender < Requester::Sender # :nodoc:
@@ -901,6 +923,12 @@ class Resolv
end
end
+ def nameserver_port
+ lazy_initialize
+ @nameserver_port ||= @nameserver.map {|i| [i, Port] }
+ @nameserver_port
+ end
+
def generate_candidates(name)
candidates = nil
name = Name.create(name)