[PATCH] resolv.rb
From:
"Stephane D'Alu" <sdalu@...>
Date:
2002-07-22 09:25:55 UTC
List:
ruby-core #236
The patch is for ruby-1.7.2.2002.07.15:
- it fixes the TCP Requester, even if not directly used by the DNS class,
some programs may want to use it (for example to perform tests on a DNS
server)
- add fields 'aa' (authoritative anwser), 'ttl', and 'rec' (recursive) to
the Resource class, so that people using Resolv::DNS#getresources
can easily access (without redefining several internal methods) the context
in which the Resource is to be used (for example a program may want to
consider differently the address of a host, if the anwser was emitted
from an authoritative server or not). But these 3 fields are more
informative and are not taken into account for Resource comparison.
can someone commit this patch, if everybody agree of course.
--- /usr/local/lib/ruby/1.7/resolv.rb Fri Jul 19 19:37:07 2002
+++ resolv.rb Mon Jul 22 00:17:58 2002
@@ -651,35 +651,44 @@
super()
@host = host
@port = port
- @sock = TCPSocket.new
- @sock.connect(host, port)
- @sock.fcntl(Fcntl::F_SETFD, 1)
@id = -1
@senders = {}
- @thread = Thread.new {
- DNSThreadGroup.add Thread.current
- loop {
- len = @sock.read(2).unpack('n')
- reply = @sock.read(len)
- msg = begin
- Message.decode(reply)
- rescue DecodeError
- STDERR.print("DNS message decoding error: #{reply.inspect}")
- next
- end
- if s = @senders[msg.id]
- s.push msg
- else
- #STDERR.print("non-handled DNS message: #{msg.inspect}")
- end
- }
- }
- end
+ @sock = nil
+ @mutex = Mutex.new
+ end
+
+ def lazy_initialize
+ @mutex.synchronize {
+ if @sock.nil?
+ @sock = TCPSocket.new(@host, @port)
+ @sock.fcntl(Fcntl::F_SETFD, 1)
+ @thread = Thread.new {
+ DNSThreadGroup.add Thread.current
+ loop {
+ len = @sock.read(2).unpack('n')[0]
+ reply = @sock.read(len)
+ msg = begin
+ Message.decode(reply)
+ rescue DecodeError
+ STDERR.print("DNS message decoding error: #{reply.inspect}")
+ next
+ end
+ if s = @senders[msg.id]
+ s.recv msg
+ else
+ #STDERR.print("non-handled DNS message: #{msg.inspect}")
+ end
+ }
+ }
+ end
+ }
+ end
def sender(msg, data, queue, host=@host, port=@port)
unless host == @host && port == @port
raise RequestError.new("host/port don't match: #{host}:#{port}")
end
+ lazy_initialize
id = Thread.exclusive { @id = (@id + 1) & 0xffff }
request = msg.encode
request[0,2] = [request.length, id].pack('nn')
@@ -688,7 +697,7 @@
class Sender < Requester::Sender
def send
- @sock.print(@msg)
+ @sock.write(@msg)
@sock.flush
end
end
@@ -978,6 +987,8 @@
end
def add_answer(name, ttl, data)
+ data.aa = @aa != 0 ? true : false
+ data.rec = @ra != 0 ? true : false
@answer << [Name.create(name), ttl, data]
end
@@ -988,6 +999,8 @@
end
def add_authority(name, ttl, data)
+ data.aa = @aa != 0 ? true : false
+ data.rec = @ra != 0 ? true : false
@authority << [Name.create(name), ttl, data]
end
@@ -998,6 +1011,8 @@
end
def add_additional(name, ttl, data)
+ data.aa = @aa != 0 ? true : false
+ data.rec = @ra != 0 ? true : false
@additional << [Name.create(name), ttl, data]
end
@@ -1232,7 +1247,9 @@
name = self.get_name
type, klass, ttl = self.get_unpack('nnN')
typeclass = Resource.get_class(type, klass)
- return name, ttl, self.get_length16 {typeclass.decode_rdata(self)}
+ data = self.get_length16 {typeclass.decode_rdata(self)}
+ data.ttl = ttl
+ return name, ttl, data
end
end
end
@@ -1250,6 +1267,9 @@
class Resource < Query
ClassHash = {}
+ attr_reader :ttl, :aa, :rec
+ attr_writer :ttl, :aa, :rec
+
def encode_rdata(msg)
raise NotImplementedError.new
end
@@ -1259,10 +1279,23 @@
end
def ==(other)
- return self.type == other.type &&
- self.instance_variables == other.instance_variables &&
- self.instance_variables.collect {|name| self.instance_eval name} ==
- other.instance_variables.collect {|name| other.instance_eval name}
+ return false unless self.type == other.type
+ siv = self.instance_variables.delete_if {|n|
+ case n
+ when "ttl", "aa", "rec" then true
+ else false
+ end
+ }
+ oiv = other.instance_variables.delete_if {|n|
+ case n
+ when "ttl", "aa", "rec" then true
+ else false
+ end
+ }
+
+ return siv == oiv &&
+ siv.collect {|name| self.instance_eval name} ==
+ oiv.collect {|name| other.instance_eval name}
end
def eql?(other)