Class: RubyDNS::Transaction
- Inherits:
-
Object
- Object
- RubyDNS::Transaction
- 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.
The main functions to complete the trasaction are: #append! (evaluate a new query and append the results), #passthrough! (pass the query to an upstream server), #respond! (compute a specific response) and #fail! (fail with an error code).
Constant Summary collapse
- DEFAULT_TTL =
The default time used for responses (24 hours).
86400
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
- #[](key) ⇒ Object
-
#add(resources, options = {}) ⇒ Object
Append a list of resources.
-
#append!(name, resource_class = nil, options = {}) ⇒ Object
Run a new query through the rules with the given name and resource type.
-
#fail!(rcode) ⇒ Object
This function indicates that there was a failure to resolve the given question.
- #failure!(*args) ⇒ Object deprecated Deprecated.
-
#initialize(server, query, question, resource_class, answer, options = {}) ⇒ Transaction
constructor
A new instance of Transaction.
-
#name ⇒ Object
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 ⇒ Object
A helper method to process the transaction on the given server.
-
#respond!(*args) ⇒ Object
The last argument can optionally be a hash of
options
. -
#to_s ⇒ Object
Shows the question name and resource class.
Constructor Details
#initialize(server, query, question, resource_class, answer, options = {}) ⇒ Transaction
Returns a new instance of Transaction.
35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/rubydns/transaction.rb', line 35 def initialize(server, query, question, resource_class, answer, = {}) @server = server @query = query @question = question @resource_class = resource_class @answer = answer @options = @question_appended = false @fiber = nil end |
Instance Attribute Details
#answer ⇒ Object (readonly)
The current full answer to the incoming query.
59 60 61 |
# File 'lib/rubydns/transaction.rb', line 59 def answer @answer end |
#options ⇒ Object (readonly)
Any options or configuration associated with the given transaction.
62 63 64 |
# File 'lib/rubydns/transaction.rb', line 62 def @options end |
#query ⇒ Object (readonly)
The incoming query which is a set of questions.
53 54 55 |
# File 'lib/rubydns/transaction.rb', line 53 def query @query end |
#question ⇒ Object (readonly)
The question that this transaction represents.
56 57 58 |
# File 'lib/rubydns/transaction.rb', line 56 def question @question end |
#resource_class ⇒ Object (readonly)
The resource_class that was requested. This is typically used to generate a response.
50 51 52 |
# File 'lib/rubydns/transaction.rb', line 50 def resource_class @resource_class end |
Instance Method Details
#[](key) ⇒ Object
64 65 66 |
# File 'lib/rubydns/transaction.rb', line 64 def [] key @options[key] end |
#add(resources, options = {}) ⇒ Object
Append a list of resources.
By default resources are appended to the answers
section, but this can be changed by setting options[:section]
to either :authority
or :additional
.
The time-to-live (TTL) of the resources can be specified using options[:ttl]
and defaults to DEFAULT_TTL
.
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/rubydns/transaction.rb', line 163 def add(resources, = {}) # Use the default options if provided: = .merge(@options) ttl = [:ttl] || DEFAULT_TTL name = [:name] || @question.to_s + "." section = ([:section] || 'answer').to_sym method = "add_#{section}".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 end |
#append!(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 transaction's answer
.
79 80 81 |
# File 'lib/rubydns/transaction.rb', line 79 def append!(name, resource_class = nil, = {}) Transaction.new(@server, @query, name, resource_class || @resource_class, @answer, ).process end |
#fail!(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 RFC2929 for more information about DNS error codes (specifically, page 3).
This function will complete deferred transactions.
195 196 197 198 199 200 201 202 203 |
# File 'lib/rubydns/transaction.rb', line 195 def fail!(rcode) append_question! if rcode.kind_of? Symbol @answer.rcode = Resolv::DNS::RCode.const_get(rcode) else @answer.rcode = rcode.to_i end end |
#failure!(*args) ⇒ Object
206 207 208 209 210 |
# File 'lib/rubydns/transaction.rb', line 206 def failure!(*args) @server.logger.warn "failure! is deprecated, use fail! instead" fail!(*args) end |
#name ⇒ Object
The name of the question, which is typically the requested hostname.
69 70 71 |
# File 'lib/rubydns/transaction.rb', line 69 def name @question.to_s end |
#passthrough(resolver, options = {}, &block) ⇒ Object
Use the given resolver to respond to the question.
A block must be supplied, and provided a valid response is received from the upstream server, this function yields with the reply and reply_name.
If options[:name]
is provided, this overrides the default query name sent to the upstream server. The same logic applies to options[:resource_class]
.
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/rubydns/transaction.rb', line 113 def passthrough(resolver, = {}, &block) query_name = [:name] || name query_resource_class = [:resource_class] || resource_class response = @server.defer do |handle| resolver.query(query_name, query_resource_class) do |response| # Not sure if this is potentially a race condition? Could fiber.resume occur before Fiber.yield? handle.resume(response) end end case response when RubyDNS::Message yield response when RubyDNS::ResolutionFailure fail!(:ServFail) else throw PassthroughError.new("Bad response from query: #{response.inspect}") end end |
#passthrough!(resolver, options = {}, &block) ⇒ Object
Use the given resolver to respond to the question. Uses passthrough
to do the lookup and merges the result.
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.
If recursion is not requested, the result is fail!(:Refused)
. This check is ignored if an explicit options[:name]
or options[:force]
is given.
If the resolver does not respond, the result is fail!(:NXDomain)
.
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/rubydns/transaction.rb', line 90 def passthrough!(resolver, = {}, &block) if @query.rd || [:force] || [:name] passthrough(resolver, ) do |response| if block_given? yield response end # Recursion is available and is being used: # See issue #26 for more details. @answer.ra = 1 @answer.merge!(response) end else raise PassthroughError.new("Request is not recursive!") end end |
#process ⇒ Object
A helper method to process the transaction on the given server. Unless the transaction is deferred, it will #succeed on completion.
213 214 215 |
# File 'lib/rubydns/transaction.rb', line 213 def process @server.process(name, @resource_class, self) end |
#respond!(*args) ⇒ Object
The last argument can optionally be a hash of options
. If options[:resource_class]
is provided, it overrides the default resource class of transaction. Additional options
are passed to #append!.
See Resolv::DNS::Resource
for more information about the various resource_classes
available (http://www.ruby-doc.org/stdlib/libdoc/resolv/rdoc/index.html).
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/rubydns/transaction.rb', line 141 def respond!(*args) append_question! = args.last.kind_of?(Hash) ? args.pop : {} resource_class = [:resource_class] || @resource_class if resource_class == nil raise ArgumentError.new("Could not instantiate resource #{resource_class}!") end @server.logger.info "Resource class: #{resource_class.inspect}" resource = resource_class.new(*args) @server.logger.info "Resource: #{resource.inspect}" add([resource], ) end |
#to_s ⇒ Object
Shows the question name and resource class. Suitable for debugging purposes.
74 75 76 |
# File 'lib/rubydns/transaction.rb', line 74 def to_s "#{name} #{@resource_class.name}" end |