Parent

RubyDNS::Transaction

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).

Constants

DEFAULT_TTL

The default time used for responses (24 hours).

Attributes

answer[R]

The current full answer to the incoming query.

options[R]

Any options or configuration associated with the given transaction.

query[R]

The incoming query which is a set of questions.

question[R]

The question that this transaction represents.

resource_class[R]

The resource_class that was requested. This is typically used to generate a response.

Public Class Methods

new(server, query, question, resource_class, answer, options = {}) click to toggle source
# File lib/rubydns/transaction.rb, line 35
def initialize(server, query, question, resource_class, answer, options = {})
        @server = server
        @query = query
        @question = question
        @resource_class = resource_class
        @answer = answer

        @options = options

        @question_appended = false

        @fiber = nil
end

Public Instance Methods

add(resources, options = {}) click to toggle source

Append a list of resources.

By default resources are appended to the `answers` section, but this can be changed by setting `options` to either `:authority` or `:additional`.

The time-to-live (TTL) of the resources can be specified using `options` and defaults to `DEFAULT_TTL`.

# File lib/rubydns/transaction.rb, line 159
def add(resources, options = {})
        # Use the default options if provided:
        options = options.merge(@options)
        
        ttl = options[:ttl] || DEFAULT_TTL
        name = options[:name] || @question.to_s + "."
        
        section = (options[: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 = {}) click to toggle source

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`.

# File lib/rubydns/transaction.rb, line 75
def append!(name, resource_class = nil, options = {})
        Transaction.new(@server, @query, name, resource_class || @resource_class, @answer, options).process
end
fail!(rcode) click to toggle source

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](www.rfc-editor.org/rfc/rfc2929.txt) for more information about DNS error codes (specifically, page 3).

**This function will complete deferred transactions.**

# File lib/rubydns/transaction.rb, line 191
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) click to toggle source

@deprecated

# File lib/rubydns/transaction.rb, line 202
def failure!(*args)
        @server.logger.warn "failure! is deprecated, use fail! instead"
        
        fail!(*args)
end
name() click to toggle source

The name of the question, which is typically the requested hostname.

# File lib/rubydns/transaction.rb, line 65
def name
        @question.to_s
end
passthrough(resolver, options = {}, &block) click to toggle source

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` is provided, this overrides the default query name sent to the upstream server. The same logic applies to `options`.

# File lib/rubydns/transaction.rb, line 109
def passthrough(resolver, options = {}, &block)
        query_name = options[:name] || name
        query_resource_class = options[: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) click to toggle source

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` or `options` is given.

If the resolver does not respond, the result is `fail!(:NXDomain)`.

# File lib/rubydns/transaction.rb, line 86
def passthrough!(resolver, options = {}, &block)
        if @query.rd || options[:force] || options[:name]
                passthrough(resolver, options) 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() click to toggle source

A helper method to process the transaction on the given server. Unless the transaction is deferred, it will {succeed} on completion.

# File lib/rubydns/transaction.rb, line 209
def process
        @server.process(name, @resource_class, self)
end
respond!(*args) click to toggle source

The last argument can optionally be a hash of `options`. If `options` 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 (www.ruby-doc.org/stdlib/libdoc/resolv/rdoc/index.html).

# File lib/rubydns/transaction.rb, line 137
def respond!(*args)
        append_question!
        
        options = args.last.kind_of?(Hash) ? args.pop : {}
        resource_class = options[: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], options)
end
to_s() click to toggle source

Shows the question name and resource class. Suitable for debugging purposes.

# File lib/rubydns/transaction.rb, line 70
def to_s
        "#{name} #{@resource_class.name}"
end

Protected Instance Methods

append_question!() click to toggle source

A typical response to a DNS request includes both the question and answer. This helper appends the question unless it looks like the user is already managing that aspect of the response.

# File lib/rubydns/transaction.rb, line 216
def append_question!
        if @answer.question.size == 0
                @answer.add_question(@question, @resource_class) unless @question_appended
        end
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.