Class: RubyDNS::Resolver
- Inherits:
-
Object
- Object
- RubyDNS::Resolver
- Includes:
- Celluloid::IO
- Defined in:
- lib/rubydns/resolver.rb
Defined Under Namespace
Classes: Request
Instance Method Summary collapse
-
#addresses_for(name, resource_class = Resolv::DNS::Resource::IN::A, options = {}) ⇒ Object
Yields a list of
Resolv::IPv4
andResolv::IPv6
addresses for the givenname
andresource_class
. -
#dispatch_request(message) ⇒ Object
Send the message to available servers.
-
#initialize(servers, options = {}) ⇒ Resolver
constructor
Servers are specified in the same manor as options[:listen], e.g.
-
#next_id! ⇒ Object
Provides the next sequence identification number which is used to keep track of DNS messages.
-
#query(name, resource_class = Resolv::DNS::Resource::IN::A) ⇒ Object
Look up a named resource of the given resource_class.
- #request_timeout ⇒ Object
Constructor Details
#initialize(servers, options = {}) ⇒ Resolver
Servers are specified in the same manor as options[:listen], e.g. [:tcp/:udp, address, port] In the case of multiple servers, they will be checked in sequence.
42 43 44 45 46 47 48 |
# File 'lib/rubydns/resolver.rb', line 42 def initialize(servers, = {}) @servers = servers @options = @logger = [:logger] || Celluloid.logger end |
Instance Method Details
#addresses_for(name, resource_class = Resolv::DNS::Resource::IN::A, options = {}) ⇒ Object
Yields a list of Resolv::IPv4
and Resolv::IPv6
addresses for the given name
and resource_class
. Raises a ResolutionFailure if no severs respond.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/rubydns/resolver.rb', line 66 def addresses_for(name, resource_class = Resolv::DNS::Resource::IN::A, = {}) ([:retries] || 5).times do response = query(name, resource_class) if response # Resolv::DNS::Name doesn't retain the trailing dot. name = name.sub(/\.$/, '') return response.answer.select{|record| record[0].to_s == name}.collect{|record| record[2].address} end # Wait 10ms before trying again: sleep 0.01 end abort ResolutionFailure.new("No server replied.") end |
#dispatch_request(message) ⇒ Object
Send the message to available servers. If no servers respond correctly, nil is returned. This result indicates a failure of the resolver to correctly contact any server and get a valid response.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/rubydns/resolver.rb', line 89 def dispatch_request() request = Request.new(, @servers) request.each do |server| @logger.debug "[#{.id}] Sending request to server #{server.inspect}" if @logger begin response = nil # This may be causing a problem, perhaps try: # after(timeout) { socket.close } # https://github.com/celluloid/celluloid-io/issues/121 timeout(request_timeout) do response = try_server(request, server) end if valid_response(, response) return response end rescue Task::TimeoutError @logger.debug "[#{.id}] Request timed out!" if @logger rescue InvalidResponseError @logger.warn "[#{.id}] Invalid response from network: #{$!}!" if @logger rescue DecodeError @logger.warn "[#{.id}] Error while decoding data from network: #{$!}!" if @logger rescue IOError @logger.warn "[#{.id}] Error while reading from network: #{$!}!" if @logger end end return nil end |
#next_id! ⇒ Object
Provides the next sequence identification number which is used to keep track of DNS messages.
51 52 53 54 |
# File 'lib/rubydns/resolver.rb', line 51 def next_id! # Using sequential numbers for the query ID is generally a bad thing because over UDP they can be spoofed. 16-bits isn't hard to guess either, but over UDP we also use a random port, so this makes effectively 32-bits of entropy to guess per request. SecureRandom.random_number(2**16) end |
#query(name, resource_class = Resolv::DNS::Resource::IN::A) ⇒ Object
Look up a named resource of the given resource_class.
57 58 59 60 61 62 63 |
# File 'lib/rubydns/resolver.rb', line 57 def query(name, resource_class = Resolv::DNS::Resource::IN::A) = Resolv::DNS::Message.new(next_id!) .rd = 1 .add_question name, resource_class dispatch_request() end |
#request_timeout ⇒ Object
84 85 86 |
# File 'lib/rubydns/resolver.rb', line 84 def request_timeout @options[:timeout] || 1 end |