Class: Async::DNS::Server
- Inherits:
-
Object
- Object
- Async::DNS::Server
- Defined in:
- lib/async/dns/server.rb
Constant Summary collapse
- DEFAULT_ENDPOINTS =
The default server interfaces
[[:udp, "0.0.0.0", 53], [:tcp, "0.0.0.0", 53]]
Instance Attribute Summary collapse
-
#logger ⇒ Object
Returns the value of attribute logger.
-
#origin ⇒ Object
Records are relative to this origin:.
Instance Method Summary collapse
-
#fire(event_name) ⇒ Object
Fire the named event as part of running the server.
-
#initialize(endpoints = DEFAULT_ENDPOINTS, origin: '.', logger: Console.logger) ⇒ Server
constructor
Instantiate a server with a block.
-
#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(*args) ⇒ Object
Setup all specified interfaces and begin accepting incoming connections.
Constructor Details
#initialize(endpoints = DEFAULT_ENDPOINTS, origin: '.', logger: Console.logger) ⇒ Server
Instantiate a server with a block
server = Server.new do match(/server.mydomain.com/, IN::A) do |transaction| transaction.respond!(“1.2.3.4”) end end
39 40 41 42 43 |
# File 'lib/async/dns/server.rb', line 39 def initialize(endpoints = DEFAULT_ENDPOINTS, origin: '.', logger: Console.logger) @endpoints = endpoints @origin = origin @logger = logger end |
Instance Attribute Details
#logger ⇒ Object
Returns the value of attribute logger.
48 49 50 |
# File 'lib/async/dns/server.rb', line 48 def logger @logger end |
#origin ⇒ Object
Records are relative to this origin:
46 47 48 |
# File 'lib/async/dns/server.rb', line 46 def origin @origin end |
Instance Method Details
#fire(event_name) ⇒ Object
Fire the named event as part of running the server.
51 52 |
# File 'lib/async/dns/server.rb', line 51 def fire(event_name) 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.
55 56 57 |
# File 'lib/async/dns/server.rb', line 55 def process(name, resource_class, transaction) raise NotImplementedError.new end |
#process_query(query, options = {}, &block) ⇒ Object
Process an incoming DNS message. Returns a serialized message to be sent back to the client.
60 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 |
# File 'lib/async/dns/server.rb', line 60 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) @logger.debug(query) {"Processing question #{question} #{resource_class}..."} transaction = Transaction.new(self, query, question, resource_class, response, ) transaction.process rescue Resolv::DNS::OriginError # This is triggered if the question is not part of the specified @origin: @logger.debug(query) {"Skipping question #{question} #{resource_class} because #{$!}"} end end rescue StandardError => error @logger.error(query) {error} response.rcode = Resolv::DNS::RCode::ServFail end end_time = Time.now @logger.debug(query) {"Time to process request: #{end_time - start_time}s"} return response end |
#run(*args) ⇒ Object
Setup all specified interfaces and begin accepting incoming connections.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/async/dns/server.rb', line 102 def run(*args) @logger.info "Starting Async::DNS server (v#{Async::DNS::VERSION})..." Async::Reactor.run do |task| fire(:setup) Async::IO::Endpoint.each(@endpoints) do |endpoint| task.async do endpoint.bind do |socket| case socket.type when Socket::SOCK_DGRAM @logger.info "<> Listening for datagrams on #{socket.local_address.inspect}" DatagramHandler.new(self, socket).run when Socket::SOCK_STREAM @logger.info "<> Listening for connections on #{socket.local_address.inspect}" StreamHandler.new(self, socket).run else raise ArgumentError.new("Don't know how to handle #{address}") end end end end fire(:start) end end |