[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]