Class: Celluloid::DNS::Server
- Inherits:
-
Object
- Object
- Celluloid::DNS::Server
- Includes:
- IO
- Defined in:
- lib/celluloid/dns/server.rb
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.
-
#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(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 ⇒ Object
Setup all specified interfaces and begin accepting incoming connections.
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
41 42 43 44 45 46 |
# File 'lib/celluloid/dns/server.rb', line 41 def initialize( = {}) @logger = [:logger] || Celluloid.logger @interfaces = [:listen] || DEFAULT_INTERFACES @origin = [:origin] || '.' end |
Instance Attribute Details
#logger ⇒ Object
Returns the value of attribute logger.
51 52 53 |
# File 'lib/celluloid/dns/server.rb', line 51 def logger @logger end |
#origin ⇒ Object
Records are relative to this origin:
49 50 51 |
# File 'lib/celluloid/dns/server.rb', line 49 def origin @origin end |
Instance Method Details
#fire(event_name) ⇒ Object
Fire the named event as part of running the server.
54 55 |
# File 'lib/celluloid/dns/server.rb', line 54 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.
66 67 68 |
# File 'lib/celluloid/dns/server.rb', line 66 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.
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 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/celluloid/dns/server.rb', line 71 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.id}> 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.id}> Skipping question #{question} #{resource_class} because #{$!}"} end end rescue StandardError => error @logger.error "<#{query.id}> Exception thrown while processing #{transaction}!" Celluloid::DNS.log_exception(@logger, error) response.rcode = Resolv::DNS::RCode::ServFail end end_time = Time.now @logger.debug {"<#{query.id}> Time to process request: #{end_time - start_time}s"} return response end |
#run ⇒ Object
Setup all specified interfaces and begin accepting incoming connections.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/celluloid/dns/server.rb', line 114 def run @logger.info "Starting Celluloid::DNS server (v#{Celluloid::DNS::VERSION})..." fire(:setup) # Setup server sockets @interfaces.each do |spec| if spec.is_a?(BasicSocket) spec.do_not_reverse_lookup protocol = spec.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE).unpack("i")[0] ip = spec.local_address.ip_address port = spec.local_address.ip_port case protocol when Socket::SOCK_DGRAM @logger.info "<> Attaching to pre-existing UDP socket #{ip}:#{port}" link UDPSocketHandler.new(self, Celluloid::IO::Socket.try_convert(spec)) when Socket::SOCK_STREAM @logger.info "<> Attaching to pre-existing TCP socket #{ip}:#{port}" link TCPSocketHandler.new(self, Celluloid::IO::Socket.try_convert(spec)) else raise ArgumentError.new("Unknown socket protocol: #{protocol}") end elsif spec[0] == :udp @logger.info "<> Listening on #{spec.join(':')}" link UDPHandler.new(self, spec[1], spec[2]) elsif spec[0] == :tcp @logger.info "<> Listening on #{spec.join(':')}" link TCPHandler.new(self, spec[1], spec[2]) else raise ArgumentError.new("Invalid connection specification: #{spec.inspect}") end end fire(:start) end |