ruby-changes:28108
From: akr <ko1@a...>
Date: Sat, 6 Apr 2013 23:32:44 +0900 (JST)
Subject: [ruby-changes:28108] akr:r40160 (trunk): * lib/resolv.rb: Add one-shot multicast DNS support.
akr 2013-04-06 23:32:34 +0900 (Sat, 06 Apr 2013) New Revision: 40160 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=40160 Log: * lib/resolv.rb: Add one-shot multicast DNS support. [ruby-core:53387] [Feature #8089] by Eric Hodel. Modified files: trunk/ChangeLog trunk/NEWS trunk/lib/resolv.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 40159) +++ ChangeLog (revision 40160) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sat Apr 6 23:31:38 2013 Tanaka Akira <akr@f...> + + * lib/resolv.rb: Add one-shot multicast DNS support. + [ruby-core:53387] [Feature #8089] by Eric Hodel. + Sat Apr 6 22:12:01 2013 Tanaka Akira <akr@f...> * lib/resolv.rb (Resolv::DNS.fetch_resource): New method to obtain Index: lib/resolv.rb =================================================================== --- lib/resolv.rb (revision 40159) +++ lib/resolv.rb (revision 40160) @@ -665,7 +665,12 @@ class Resolv https://github.com/ruby/ruby/blob/trunk/lib/resolv.rb#L665 def request(sender, tout) start = Time.now timelimit = start + tout - sender.send + begin + sender.send + rescue Errno::EHOSTUNREACH + # multi-homed IPv6 may generate this + raise ResolvTimeout + end while true before_select = Time.now timeout = timelimit - before_select @@ -691,7 +696,7 @@ class Resolv https://github.com/ruby/ruby/blob/trunk/lib/resolv.rb#L696 rescue DecodeError next # broken DNS message ignored end - if s = @senders[[from,msg.id]] + if s = sender_for(from, msg) break else # unexpected DNS message ignored @@ -700,6 +705,10 @@ class Resolv https://github.com/ruby/ruby/blob/trunk/lib/resolv.rb#L705 return msg, s.data end + def sender_for(addr, msg) + @senders[[addr,msg.id]] + end + def close socks = @socks @socks = nil @@ -820,6 +829,22 @@ class Resolv https://github.com/ruby/ruby/blob/trunk/lib/resolv.rb#L829 end end + class MDNSOneShot < UnconnectedUDP # :nodoc: + def sender(msg, data, host, port=Port) + service = [host, port] + id = DNS.allocate_request_id(host, port) + request = msg.encode + request[0,2] = [id].pack('n') + sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"] + return @senders[id] = + UnconnectedUDP::Sender.new(request, data, sock, host, port) + end + + def sender_for(addr, msg) + @senders[msg.id] + end + end + class TCP < Requester # :nodoc: def initialize(host, port=Port) super() @@ -2388,11 +2413,96 @@ class Resolv https://github.com/ruby/ruby/blob/trunk/lib/resolv.rb#L2413 end ## + # Resolv::MDNS is a one-shot Multicast DNS (mDNS) resolver. It blindly + # makes queries to the mDNS addresses without understanding anything about + # multicast ports. + # + # Information taken form the following places: + # + # * RFC 6762 + + class MDNS < DNS + + ## + # Default mDNS Port + + Port = 5353 + + ## + # Default IPv4 mDNS address + + AddressV4 = '224.0.0.251' + + ## + # Default IPv6 mDNS address + + AddressV6 = 'ff02::fb' + + ## + # Default mDNS addresses + + Addresses = [ + [AddressV4, Port], + [AddressV6, Port], + ] + + ## + # Creates a new one-shot Multicast DNS (mDNS) resolver. + # + # +config_info+ can be: + # + # nil:: + # Uses the default mDNS addresses + # + # Hash:: + # Must contain :nameserver or :nameserver_port like + # Resolv::DNS#initialize. + + def initialize(config_info=nil) + if config_info then + super({ nameserver_port: Addresses }.merge(config_info)) + else + super(nameserver_port: Addresses) + end + end + + ## + # Iterates over all IP addresses for +name+ retrieved from the mDNS + # resolver, provided name ends with "local". If the name does not end in + # "local" no records will be returned. + # + # +name+ can be a Resolv::DNS::Name or a String. Retrieved addresses will + # be a Resolv::IPv4 or Resolv::IPv6 + + def each_address(name) + name = Resolv::DNS::Name.create(name) + + return unless name.to_a.last == 'local' + + super(name) + end + + def make_udp_requester # :nodoc: + nameserver_port = @config.nameserver_port + Requester::MDNSOneShot.new(*nameserver_port) + end + + end + + ## # Default resolver to use for Resolv class methods. DefaultResolver = self.new ## + # Replaces the resolvers in the default resolver with +new_resolvers+. This + # allows resolvers to be changed for resolv-replace. + + def DefaultResolver.replace_resolvers new_resolvers + @resolvers = new_resolvers + end + + ## # Address Regexp to use for matching IP addresses. AddressRegex = /(?:#{IPv4::Regex})|(?:#{IPv6::Regex})/ Index: NEWS =================================================================== --- NEWS (revision 40159) +++ NEWS (revision 40160) @@ -49,6 +49,7 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L49 * Resolv * New methods: * Resolv::DNS.fetch_resource + * One-shot multicast DNS support * Rinda::RingServer, Rinda::RingFinger * Rinda now supports multicast sockets. See Rinda::RingServer and -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/