Class: RubyDNS::Transaction
- Inherits:
-
Object
- Object
- RubyDNS::Transaction
- Includes:
- EventMachine::Deferrable
- Defined in:
- lib/rubydns/transaction.rb
Overview
This class provides all details of a single DNS question and answer. This is used by the DSL to provide DNS related functionality.
Instance Attribute Summary collapse
-
#answer ⇒ Object
readonly
The current full answer to the incoming query.
-
#options ⇒ Object
readonly
Any options or configuration associated with the given transaction.
-
#query ⇒ Object
readonly
The incoming query which is a set of questions.
-
#question ⇒ Object
readonly
The question that this transaction represents.
-
#resource_class ⇒ Object
readonly
The resource_class that was requested.
Instance Method Summary collapse
-
#append!(*resources) ⇒ Object
Append a given set of resources to the answer.
-
#append_query!(name, resource_class = nil, options = {}) ⇒ Object
Run a new query through the rules with the given name and resource type.
- #append_question! ⇒ Object
- #defer! ⇒ Object
-
#failure!(rcode) ⇒ Object
This function indicates that there was a failure to resolve the given question.
-
#initialize(server, query, question, resource_class, answer, options = {}) ⇒ Transaction
constructor
A new instance of Transaction.
-
#name ⇒ Object
Return the name of the question, which is typically the requested hostname.
-
#passthrough(resolver, options = {}, &block) ⇒ Object
Use the given resolver to respond to the question.
-
#passthrough!(resolver, options = {}, &block) ⇒ Object
Use the given resolver to respond to the question.
- #process(&finished) ⇒ Object
-
#respond!(*data) ⇒ Object
Respond to the given query with a resource record.
-
#to_s ⇒ Object
Suitable for debugging purposes.
Constructor Details
#initialize(server, query, question, resource_class, answer, options = {}) ⇒ Transaction
Returns a new instance of Transaction.
30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/rubydns/transaction.rb', line 30 def initialize(server, query, question, resource_class, answer, = {}) @server = server @query = query @question = question @resource_class = resource_class @answer = answer @options = @deferred = false @question_appended = false end |
Instance Attribute Details
#answer ⇒ Object (readonly)
The current full answer to the incoming query.
54 55 56 |
# File 'lib/rubydns/transaction.rb', line 54 def answer @answer end |
#options ⇒ Object (readonly)
Any options or configuration associated with the given transaction.
57 58 59 |
# File 'lib/rubydns/transaction.rb', line 57 def @options end |
#query ⇒ Object (readonly)
The incoming query which is a set of questions.
48 49 50 |
# File 'lib/rubydns/transaction.rb', line 48 def query @query end |
#question ⇒ Object (readonly)
The question that this transaction represents.
51 52 53 |
# File 'lib/rubydns/transaction.rb', line 51 def question @question end |
#resource_class ⇒ Object (readonly)
The resource_class that was requested. This is typically used to generate a response.
45 46 47 |
# File 'lib/rubydns/transaction.rb', line 45 def resource_class @resource_class end |
Instance Method Details
#append!(*resources) ⇒ Object
Append a given set of resources to the answer. The last argument can optionally be a hash of options.
options[:ttl]
-
Specify the TTL for the resource
options[:name]
-
Override the name (question) of the response.
options[:section]
-
Specify whether the response should go in the ‘:answer`
`:authority` or `:additional` section.
This function can be used to supply multiple responses to a given question. For example, each argument is expected to be an instantiated resource from Resolv::DNS::Resource
module.
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/rubydns/transaction.rb', line 191 def append! (*resources) append_question! if resources.last.kind_of?(Hash) = resources.pop else = {} end # Use the default options if provided: = .merge(@options) [:ttl] ||= 16000 [:name] ||= @question.to_s + "." method = ("add_" + ([:section] || 'answer').to_s).to_sym resources.each do |resource| @server.logger.debug "#{method}: #{resource.inspect} #{resource.class::TypeValue} #{resource.class::ClassValue}" @answer.send(method, [:name], [:ttl], resource) end succeed if @deferred true end |
#append_query!(name, resource_class = nil, options = {}) ⇒ Object
Run a new query through the rules with the given name and resource type. The results of this query are appended to the current transactions answer
.
71 72 73 |
# File 'lib/rubydns/transaction.rb', line 71 def append_query!(name, resource_class = nil, = {}) Transaction.new(@server, @query, name, resource_class || @resource_class, @answer, ).process end |
#append_question! ⇒ Object
251 252 253 254 255 |
# File 'lib/rubydns/transaction.rb', line 251 def append_question! if @answer.question.size == 0 @answer.add_question(@question, @resource_class) unless @question_appended end end |
#defer! ⇒ Object
83 84 85 |
# File 'lib/rubydns/transaction.rb', line 83 def defer! @deferred = true end |
#failure!(rcode) ⇒ Object
This function indicates that there was a failure to resolve the given question. The single argument must be an integer error code, typically given by the constants in Resolv::DNS::RCode
.
The easiest way to use this function it to simply supply a symbol. Here is a list of the most commonly used ones:
:NoError
-
No error occurred.
:FormErr
:: The incoming data was not formatted correctly.
:ServFail
-
The operation caused a server failure (internal error, etc).
:NXDomain
-
Non-eXistant Domain (domain record does not exist).
:NotImp
-
The operation requested is not implemented.
:Refused
-
The operation was refused by the server.
:NotAuth
-
The server is not authoritive for the zone.
See www.rfc-editor.org/rfc/rfc2929.txt for more information about DNS error codes (specifically, page 3).
236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/rubydns/transaction.rb', line 236 def failure! (rcode) append_question! if rcode.kind_of? Symbol @answer.rcode = Resolv::DNS::RCode.const_get(rcode) else @answer.rcode = rcode.to_i end # The transaction itself has completed, but contains a failure: succeed(rcode) if @deferred true end |
#name ⇒ Object
Return the name of the question, which is typically the requested hostname.
60 61 62 |
# File 'lib/rubydns/transaction.rb', line 60 def name @question.to_s end |
#passthrough(resolver, options = {}, &block) ⇒ Object
Use the given resolver to respond to the question. If recursion is not requested, the result is failure!(:Refused)
. If the resolver does not respond, the result is failure!(:NXDomain)
If a block is supplied, this function yields with the reply and reply_name if successful. This block is responsible for doing something useful with the reply, such as merging it or conditionally discarding it.
A second argument, options, provides some control over the passthrough process. :force => true, ensures that the query will occur even if recursion is not requested. :name => resource_name, override the name for the request as it is passed to the resolver. Implies :force. :resource_class => class, overried the resource class for a request as it is passed to the resolver.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/rubydns/transaction.rb', line 122 def passthrough(resolver, = {}, &block) if @query.rd || [:force] || [:name] # Resolver is asynchronous, so we are now deferred: defer! query_name = [:name] || name query_resource_class = [:resource_class] || resource_class resolver.query(query_name, query_resource_class) do |response| case response when RubyDNS::Message yield response when RubyDNS::ResolutionFailure failure!(:ServFail) else # This shouldn't ever happen, but if it does for some reason we shouldn't hang. fail(response) end end else failure!(:Refused) end true end |
#passthrough!(resolver, options = {}, &block) ⇒ Object
Use the given resolver to respond to the question. The default functionality is implemented by passthrough, and if a reply is received, it will be merged with the answer for this transaction.
If a block is supplied, this function yields with the reply and reply_name if successful. This could be used, for example, to update a cache or modify the reply.
94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/rubydns/transaction.rb', line 94 def passthrough!(resolver, = {}, &block) passthrough(resolver, ) do |response| if block_given? yield response end @answer.merge!(response) succeed if @deferred end true end |
#process(&finished) ⇒ Object
75 76 77 78 79 80 81 |
# File 'lib/rubydns/transaction.rb', line 75 def process(&finished) @server.process(name, @resource_class, self) unless @deferred succeed(self) end end |
#respond!(*data) ⇒ Object
Respond to the given query with a resource record. The arguments to this function depend on the resource_class
requested. The last argument can optionally be a hash of options.
options[:resource_class]
-
Override the default
resource_class
options[:ttl]
-
Specify the TTL for the resource
options[:name]
-
Override the name (question) of the response.
- for A records
-
respond!("1.2.3.4")
- for MX records
-
respond!(10, Name.create("mail.blah.com"))
This function instantiates the resource class with the supplied arguments, and then passes it to append!
.
See Resolv::DNS::Resource
for more information about the various resource_class
s available. www.ruby-doc.org/stdlib/libdoc/resolv/rdoc/index.html
165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/rubydns/transaction.rb', line 165 def respond! (*data) = data.last.kind_of?(Hash) ? data.pop : {} resource_class = [:resource_class] || @resource_class if resource_class == nil raise ArgumentError, "Could not instantiate resource #{resource_class}!" end @server.logger.info "Resource class: #{resource_class.inspect}" resource = resource_class.new(*data) @server.logger.info "Resource: #{resource.inspect}" append!(resource, ) end |
#to_s ⇒ Object
Suitable for debugging purposes
65 66 67 |
# File 'lib/rubydns/transaction.rb', line 65 def to_s "#{name} #{@resource_class.name}" end |