Project

General

Profile

Feature #8089 ยป resolv.rb.one-shot-mdns.patch

drbrain (Eric Hodel), 03/14/2013 08:41 AM

View differences:

lib/resolv.rb (working copy)
659 659
      def request(sender, tout)
660 660
        start = Time.now
661 661
        timelimit = start + tout
662
        sender.send
662
        begin
663
          sender.send
664
        rescue Errno::EHOSTUNREACH
665
          # multi-homed IPv6 may generate this
666
          raise ResolvTimeout
667
        end
663 668
        while true
664 669
          before_select = Time.now
665 670
          timeout = timelimit - before_select
......
685 690
          rescue DecodeError
686 691
            next # broken DNS message ignored
687 692
          end
688
          if s = @senders[[from,msg.id]]
693
          if s = sender_for(from, msg)
689 694
            break
690 695
          else
691 696
            # unexpected DNS message ignored
......
694 699
        return msg, s.data
695 700
      end
696 701

  
702
      def sender_for(addr, msg)
703
        @senders[[addr,msg.id]]
704
      end
705

  
697 706
      def close
698 707
        socks = @socks
699 708
        @socks = nil
......
814 823
        end
815 824
      end
816 825

  
826
      class MDNSOneShot < UnconnectedUDP # :nodoc:
827
        def sender(msg, data, host, port=Port)
828
          service = [host, port]
829
          id = DNS.allocate_request_id(host, port)
830
          request = msg.encode
831
          request[0,2] = [id].pack('n')
832
          sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
833
          return @senders[id] =
834
            UnconnectedUDP::Sender.new(request, data, sock, host, port)
835
        end
836

  
837
        def sender_for(addr, msg)
838
          @senders[msg.id]
839
        end
840
      end
841

  
817 842
      class TCP < Requester # :nodoc:
818 843
        def initialize(host, port=Port)
819 844
          super()
......
2382 2407
  end
2383 2408

  
2384 2409
  ##
2410
  # Resolv::MDNS is a one-shot Multicast DNS (mDNS) resolver.  It blindly
2411
  # makes queries to the mDNS addresses without understanding anything about
2412
  # multicast ports.
2413
  #
2414
  # Information taken form the following places:
2415
  #
2416
  # * RFC 6762
2417

  
2418
  class MDNS < DNS
2419

  
2420
    ##
2421
    # Default mDNS Port
2422

  
2423
    Port = 5353
2424

  
2425
    ##
2426
    # Default IPv4 mDNS address
2427

  
2428
    AddressV4 = '224.0.0.251'
2429

  
2430
    ##
2431
    # Default IPv6 mDNS address
2432

  
2433
    AddressV6 = 'ff02::fb'
2434

  
2435
    ##
2436
    # Default mDNS addresses
2437

  
2438
    Addresses = [
2439
      [AddressV4, Port],
2440
      [AddressV6, Port],
2441
    ]
2442

  
2443
    ##
2444
    # Creates a new one-shot Multicast DNS (mDNS) resolver.
2445
    #
2446
    # +config_info+ can be:
2447
    #
2448
    # nil::
2449
    #   Uses the default mDNS addresses
2450
    #
2451
    # Hash::
2452
    #   Must contain :nameserver or :nameserver_port like
2453
    #   Resolv::DNS#initialize.
2454

  
2455
    def initialize(config_info=nil)
2456
      if config_info then
2457
        super({ nameserver_port: Addresses }.merge(config_info))
2458
      else
2459
        super(nameserver_port: Addresses)
2460
      end
2461
    end
2462

  
2463
    ##
2464
    # Iterates over all IP addresses for +name+ retrieved from the mDNS
2465
    # resolver, provided name ends with "local".  If the name does not end in
2466
    # "local" no records will be returned.
2467
    #
2468
    # +name+ can be a Resolv::DNS::Name or a String.  Retrieved addresses will
2469
    # be a Resolv::IPv4 or Resolv::IPv6
2470

  
2471
    def each_address(name)
2472
      name = Resolv::DNS::Name.create(name)
2473

  
2474
      return unless name.to_a.last == 'local'
2475

  
2476
      super(name)
2477
    end
2478

  
2479
    def make_udp_requester # :nodoc:
2480
      nameserver_port = @config.nameserver_port
2481
      Requester::MDNSOneShot.new(*nameserver_port)
2482
    end
2483

  
2484
  end
2485

  
2486
  ##
2385 2487
  # Default resolver to use for Resolv class methods.
2386 2488

  
2387 2489
  DefaultResolver = self.new
2388 2490

  
2389 2491
  ##
2492
  # Replaces the resolvers in the default resolver with +new_resolvers+.  This
2493
  # allows resolvers to be changed for resolv-replace.
2494

  
2495
  def DefaultResolver.replace_resolvers new_resolvers
2496
    @resolvers = new_resolvers
2497
  end
2498

  
2499
  ##
2390 2500
  # Address Regexp to use for matching IP addresses.
2391 2501

  
2392 2502
  AddressRegex = /(?:#{IPv4::Regex})|(?:#{IPv6::Regex})/