Class: Async::DNS::Server
- Inherits:
-
Object
- Object
- Async::DNS::Server
- Defined in:
- lib/async/dns/server.rb
Overview
A DNS server which can be used to resolve queries.
Instance Attribute Summary collapse
-
#origin ⇒ String
Records are relative to this origin.
Class Method Summary collapse
-
.default_endpoint(port = 53) ⇒ Object
The default endpoint to listen on.
Instance Method Summary collapse
-
#initialize(endpoint = self.class.default_endpoint, origin: ".") ⇒ Server
constructor
Instantiate a server with a block.
-
#logger ⇒ Object
deprecated
Deprecated.
Use Console instead.
-
#process(name, resource_class, transaction) ⇒ Object
Give a name and a record type, try to match a rule and use it for processing the given arguments.
-
#process_query(query, options = {}, &block) ⇒ Object
Process an incoming DNS message.
-
#run ⇒ Object
Setup all specified interfaces and begin accepting incoming connections.
Constructor Details
#initialize(endpoint = self.class.default_endpoint, origin: ".") ⇒ Server
Instantiate a server with a block.
36 37 38 39 |
# File 'lib/async/dns/server.rb', line 36 def initialize(endpoint = self.class.default_endpoint, origin: ".") @endpoint = endpoint @origin = origin end |
Instance Attribute Details
#origin ⇒ String
Records are relative to this origin.
44 45 46 |
# File 'lib/async/dns/server.rb', line 44 def origin @origin end |
Class Method Details
.default_endpoint(port = 53) ⇒ Object
The default endpoint to listen on.
24 25 26 27 28 29 |
# File 'lib/async/dns/server.rb', line 24 def self.default_endpoint(port = 53) ::IO::Endpoint.composite( ::IO::Endpoint.udp("localhost", port), ::IO::Endpoint.tcp("localhost", port) ) end |
Instance Method Details
#logger ⇒ Object
Use Console instead.
47 48 49 |
# File 'lib/async/dns/server.rb', line 47 def logger Console end |
#process(name, resource_class, transaction) ⇒ Object
Give a name and a record type, try to match a rule and use it for processing the given arguments.
56 57 58 |
# File 'lib/async/dns/server.rb', line 56 def process(name, resource_class, transaction) transaction.fail!(:NXDomain) end |
#process_query(query, options = {}, &block) ⇒ Object
Process an incoming DNS message. Returns a serialized message to be sent back to the client.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/async/dns/server.rb', line 61 def process_query(query, = {}, &block) start_time = Time.now # Setup response response = Resolv::DNS::Message::new(query.id) response.qr = 1 # 0 = Query, 1 = Response response.opcode = query.opcode # Type of Query; copy from query response.aa = 1 # Is this an authoritative response: 0 = No, 1 = Yes response.rd = query.rd # Is Recursion Desired, copied from query response.ra = 0 # Does name server support recursion: 0 = No, 1 = Yes response.rcode = 0 # Response code: 0 = No errors transaction = nil begin query.question.each do |question, resource_class| begin question = question.without_origin(@origin) Console.debug(query) {"Processing question #{question} #{resource_class}..."} transaction = Transaction.new(self, query, question, resource_class, response, **) transaction.process rescue Resolv::DNS::OriginError => error # This is triggered if the question is not part of the specified @origin: Console.error(self, "Failed to process question #{question} #{resource_class}!", error: error) end end rescue StandardError => error Console.error(query) {error} response.rcode = Resolv::DNS::RCode::ServFail end end_time = Time.now Console.debug(query) {"Time to process request: #{end_time - start_time}s"} return response end |
#run ⇒ Object
Setup all specified interfaces and begin accepting incoming connections.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/async/dns/server.rb', line 103 def run Console.info "Starting Async::DNS server (v#{Async::DNS::VERSION})..." Async do |task| wrapper = @endpoint.wrapper @endpoint.bind do |server| Console.info "<> Listening for connections on #{server.local_address.inspect}" case server.local_address.socktype when Socket::SOCK_DGRAM DatagramHandler.new(self, server).run(wrapper) when Socket::SOCK_STREAM StreamHandler.new(self, server).run(wrapper) else raise ArgumentError.new("Don't know how to handle #{server}") end end end end |