Module: RubyDNS::UDPHandler

Includes:
Peername
Defined in:
lib/rubydns/handler.rb

Overview

Handling incoming UDP requests, which are single data packets, and pass them on to the given server.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.process(server, data, options = {}, &block) ⇒ Object

Process a packet of data with the given server. If an exception is thrown, a failure message will be sent back.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/rubydns/handler.rb', line 41

def self.process(server, data, options = {}, &block)
	server.logger.debug {"Receiving incoming query (#{data.bytesize} bytes)..."}
	query = nil

	begin
		query = RubyDNS::decode_message(data)

		return server.process_query(query, options, &block)
	rescue => error
		server.logger.error "Error processing request!"
		server.logger.error "#{error.class}: #{error.message}"

		error.backtrace.each { |at| server.logger.error at }

		# Encoding may fail, so we need to handle this particular case:
		server_failure = Resolv::DNS::Message::new(query ? query.id : 0)
		server_failure.qr = 1
		server_failure.opcode = query ? query.opcode : 0
		server_failure.aa = 1
		server_failure.rd = 0
		server_failure.ra = 0

		server_failure.rcode = Resolv::DNS::RCode::ServFail

		# We can't do anything at this point...
		yield server_failure
	end
end

Instance Method Details

#initialize(server) ⇒ Object



36
37
38
# File 'lib/rubydns/handler.rb', line 36

def initialize(server)
	@server = server
end

#peernameObject



70
71
72
# File 'lib/rubydns/handler.rb', line 70

def peername
	Socket.unpack_sockaddr_in(self.get_peername)
end

#receive_data(data) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/rubydns/handler.rb', line 74

def receive_data(data)
	options = {:connection => self}
	
	UDPHandler.process(@server, data, options) do |answer|
		data = answer.encode
		
		@server.logger.debug {"Writing response to client (#{data.bytesize} bytes) via UDP..."}
		
		if data.bytesize > UDP_TRUNCATION_SIZE
			@server.logger.warn {"Response via UDP was larger than #{UDP_TRUNCATION_SIZE}!"}
			
			# Reencode data with truncation flag marked as true:
			truncation_error = Resolv::DNS::Message.new(answer.id)
			truncation_error.tc = 1
			
			data = truncation_error.encode
		end
		
		# We explicitly use the ip and port given, because we found that send_data was unreliable in a callback.
		# self.send_datagram(data, peer_ip, peer_port)
		self.send_data(data)
	end
end