Class: RubyDNS::Server
- Inherits:
-
Object
- Object
- RubyDNS::Server
- Defined in:
- lib/rubydns/server.rb
Direct Known Subclasses
Constant Summary collapse
- DEFAULT_INTERFACES =
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.
Instance Method Summary collapse
-
#defer {|fiber| ... } ⇒ Object
Process a block with the current fiber.
-
#fire(event_name) ⇒ Object
Fire the named event as part of running the server.
-
#initialize(options) ⇒ 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(options = {}) ⇒ Object
By default the server runs on port 53, both TCP and UDP, which is usually a priviledged port and requires root access to bind.
Constructor Details
#initialize(options) ⇒ 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
40 41 42 |
# File 'lib/rubydns/server.rb', line 40 def initialize() @logger = [:logger] || Logger.new($stderr) end |
Instance Attribute Details
#logger ⇒ Object
Returns the value of attribute logger.
44 45 46 |
# File 'lib/rubydns/server.rb', line 44 def logger @logger end |
Instance Method Details
#defer {|fiber| ... } ⇒ Object
Process a block with the current fiber. To resume processing from the block, call fiber.resume
. You shouldn't call fiber.resume
until after the top level block has returned.
56 57 58 59 60 61 62 |
# File 'lib/rubydns/server.rb', line 56 def defer(&block) fiber = Fiber.current yield(fiber) Fiber.yield end |
#fire(event_name) ⇒ Object
Fire the named event as part of running the server.
47 48 |
# File 'lib/rubydns/server.rb', line 47 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.
51 52 53 |
# File 'lib/rubydns/server.rb', line 51 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.
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/rubydns/server.rb', line 65 def process_query(query, = {}, &block) start_time = Time.now # Setup answer answer = Resolv::DNS::Message::new(query.id) answer.qr = 1 # 0 = Query, 1 = Response answer.opcode = query.opcode # Type of Query; copy from query answer.aa = 1 # Is this an authoritative response: 0 = No, 1 = Yes answer.rd = query.rd # Is Recursion Desired, copied from query answer.ra = 0 # Does name server support recursion: 0 = No, 1 = Yes answer.rcode = 0 # Response code: 0 = No errors Fiber.new do transaction = nil begin query.question.each do |question, resource_class| @logger.debug {"[#{query.id}] Processing question #{question} #{resource_class}..."} transaction = Transaction.new(self, query, question, resource_class, answer, ) transaction.process end rescue @logger.error {"[#{query.id}] Exception thrown while processing #{transaction}!"} RubyDNS.log_exception(@logger, $!) answer.rcode = Resolv::DNS::RCode::ServFail end yield answer end_time = Time.now @logger.debug {"[#{query.id}] Time to process request: #{end_time - start_time}s"} end.resume end |
#run(options = {}) ⇒ Object
By default the server runs on port 53, both TCP and UDP, which is usually a priviledged port and requires root access to bind. You can change this by specifying options[:listen]
which should contain an array of [protocol, interface address, port]
specifications.
INTERFACES = [[:udp, "0.0.0.0", 5300]] RubyDNS::run_server(:listen => INTERFACES) do ... end
You can specify already connected sockets if need be:
socket = UDPSocket.new; socket.bind("0.0.0.0", 53) Process::Sys.setuid(server_uid) INTERFACES = [socket]
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/rubydns/server.rb', line 116 def run( = {}) @logger.info "Starting RubyDNS server (v#{RubyDNS::VERSION})..." interfaces = [:listen] || DEFAULT_INTERFACES fire(:setup) # Setup server sockets interfaces.each do |spec| @logger.info "Listening on #{spec.join(':')}" if spec[0] == :udp EventMachine.open_datagram_socket(spec[1], spec[2], UDPHandler, self) elsif spec[0] == :tcp EventMachine.start_server(spec[1], spec[2], TCPHandler, self) end end fire(:start) end |