toolmantim-zeroconf 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +44 -0
 - data/Rakefile +71 -0
 - data/lib/dnssd.rb +137 -0
 - data/lib/net/dns.rb +49 -0
 - data/lib/net/dns/mdns-sd.rb +240 -0
 - data/lib/net/dns/mdns.rb +1189 -0
 - data/lib/net/dns/resolv-mdns.rb +230 -0
 - data/lib/net/dns/resolv-replace.rb +66 -0
 - data/lib/net/dns/resolv.rb +2012 -0
 - data/lib/net/dns/resolvx.rb +219 -0
 - data/lib/zeroconf.rb +15 -0
 - data/lib/zeroconf/common.rb +0 -0
 - data/lib/zeroconf/ext.rb +7 -0
 - data/lib/zeroconf/pure.rb +13 -0
 - data/lib/zeroconf/version.rb +3 -0
 - data/originals/dnssd-0.6.0/COPYING +56 -0
 - data/originals/dnssd-0.6.0/README +50 -0
 - data/originals/net-mdns-0.4/COPYING +58 -0
 - data/originals/net-mdns-0.4/README +21 -0
 - data/originals/net-mdns-0.4/TODO +278 -0
 - data/samples/exhttp.rb +50 -0
 - data/samples/exhttpv1.rb +29 -0
 - data/samples/exwebrick.rb +56 -0
 - data/samples/mdns-watch.rb +132 -0
 - data/samples/mdns.rb +238 -0
 - data/samples/test_dns.rb +128 -0
 - data/samples/v1demo.rb +167 -0
 - data/samples/v1mdns.rb +111 -0
 - data/test/stress/stress_register.rb +48 -0
 - data/test/test_browse.rb +24 -0
 - data/test/test_highlevel_api.rb +35 -0
 - data/test/test_register.rb +32 -0
 - data/test/test_resolve.rb +23 -0
 - data/test/test_resolve_ichat.rb +56 -0
 - data/test/test_textrecord.rb +58 -0
 - metadata +93 -0
 
    
        data/samples/mdns.rb
    ADDED
    
    | 
         @@ -0,0 +1,238 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/local/bin/ruby18 -w
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Author: Sam Roberts <sroberts@uniserve.com>
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Licence: this file is placed in the public domain
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            $:.unshift(File.dirname($0))
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            require 'getoptlong'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            $stdout.sync = true
         
     | 
| 
      
 10 
     | 
    
         
            +
            $stderr.sync = true
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            =begin
         
     | 
| 
      
 13 
     | 
    
         
            +
            Apple's dns-sd options:
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              mdns -E                  (Enumerate recommended registration domains)
         
     | 
| 
      
 16 
     | 
    
         
            +
              mdns -F                      (Enumerate recommended browsing domains)
         
     | 
| 
      
 17 
     | 
    
         
            +
              mdns -B        <Type> <Domain>         (Browse for service instances)
         
     | 
| 
      
 18 
     | 
    
         
            +
              mdns -L <Name> <Type> <Domain>           (Look up a service instance)
         
     | 
| 
      
 19 
     | 
    
         
            +
              mdns -R <Name> <Type> <Domain> <Port> [<TXT>...] (Register a service)
         
     | 
| 
      
 20 
     | 
    
         
            +
              mdns -P <Name> <Type> <Domain> <Port> <Host> <IP> [<TXT>...]  (Proxy)
         
     | 
| 
      
 21 
     | 
    
         
            +
              mdns -Q <FQDN> <rrtype> <rrclass> (Generic query for any record type)
         
     | 
| 
      
 22 
     | 
    
         
            +
            =end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            @debug = false
         
     | 
| 
      
 25 
     | 
    
         
            +
            @log   = nil
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            @recursive = false
         
     | 
| 
      
 28 
     | 
    
         
            +
            @domain = 'local'
         
     | 
| 
      
 29 
     | 
    
         
            +
            @type = nil
         
     | 
| 
      
 30 
     | 
    
         
            +
            @name = nil
         
     | 
| 
      
 31 
     | 
    
         
            +
            @port = nil
         
     | 
| 
      
 32 
     | 
    
         
            +
            @txt  = {}
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            @cmd = nil
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            # TODO - can I use introspection on class names to determine all supported
         
     | 
| 
      
 38 
     | 
    
         
            +
            # RR types in DNS::Resource::IN?
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            HELP =<<EOF
         
     | 
| 
      
 41 
     | 
    
         
            +
            Usage: 
         
     | 
| 
      
 42 
     | 
    
         
            +
              mdns [options] -B        <type> [domain]         (Browse for service instances)
         
     | 
| 
      
 43 
     | 
    
         
            +
              mdns [options] -L <name> <type> [domain]           (Look up a service instance)
         
     | 
| 
      
 44 
     | 
    
         
            +
              mdns [options] -R <name> <type> [domain] <port> [<TXT>...] (Register a service)
         
     | 
| 
      
 45 
     | 
    
         
            +
              mdns [options] -Q <fqdn> [rrtype] [rrclass] (Generic query for any record type)
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            Note: -Q is not yet implemented.
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            For -B, -L, and -R, [domain] is optional and defaults to "local".
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            For -Q, [rrtype] defaults to A, other values are TXT, PTR, SRV, CNAME, ...
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            For -Q, [rrclass] defaults to 1 (IN).
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            [<TXT>...] is optional for -R, it can be a series of key=value pairs.
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            You can use long names --browse, --lookup, and --register instead of -B, -L,
         
     | 
| 
      
 59 
     | 
    
         
            +
            and -R.
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            Options:
         
     | 
| 
      
 62 
     | 
    
         
            +
              -m,--mdnssd   Attempt to use 'net/dns/mdns-sd', a pure-ruby DNS-SD resolver
         
     | 
| 
      
 63 
     | 
    
         
            +
                            library (this is the default).
         
     | 
| 
      
 64 
     | 
    
         
            +
              -n,--dnssd    Attempt to use 'dnssd', the interface to the native ("-n")
         
     | 
| 
      
 65 
     | 
    
         
            +
                            DNS-SD resolver library APIs, "dns_sd.h" from Apple.
         
     | 
| 
      
 66 
     | 
    
         
            +
              -d,--debug    Print debug messages to stderr.
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            Examples:
         
     | 
| 
      
 69 
     | 
    
         
            +
              mdns -B _http._tcp
         
     | 
| 
      
 70 
     | 
    
         
            +
              mdns -L "My Music" _daap._tcp
         
     | 
| 
      
 71 
     | 
    
         
            +
              mdns -R me _example._tcp local 4321 key=value key2=value2
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            These work with the test modes of Apple's dns-sd utility:
         
     | 
| 
      
 74 
     | 
    
         
            +
              mdns -L Test _testupdate._tcp     (for dns-sd -A, -U, -N)
         
     | 
| 
      
 75 
     | 
    
         
            +
              mdns -L Test _testlargetxt._tcp   (for dns-sd -T)
         
     | 
| 
      
 76 
     | 
    
         
            +
              mdns -L Test _testdualtxt._tcp    (for dns-sd -M)
         
     | 
| 
      
 77 
     | 
    
         
            +
              mdns -L Test _testtxt._tcp        (for dns-sd -I)
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            EOF
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            opts = GetoptLong.new(
         
     | 
| 
      
 82 
     | 
    
         
            +
              [ "--debug",    "-d",               GetoptLong::NO_ARGUMENT ],
         
     | 
| 
      
 83 
     | 
    
         
            +
              [ "--help",     "-h",               GetoptLong::NO_ARGUMENT ],
         
     | 
| 
      
 84 
     | 
    
         
            +
              [ "--dnssd",    "-n",               GetoptLong::NO_ARGUMENT ],
         
     | 
| 
      
 85 
     | 
    
         
            +
              [ "--mdnssd",   "-m",               GetoptLong::NO_ARGUMENT ],
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
              [ "--browse",    "-B",              GetoptLong::NO_ARGUMENT ],
         
     | 
| 
      
 88 
     | 
    
         
            +
              [ "--lookup",    "-L",              GetoptLong::NO_ARGUMENT ],
         
     | 
| 
      
 89 
     | 
    
         
            +
              [ "--register",  "-R",              GetoptLong::NO_ARGUMENT ]
         
     | 
| 
      
 90 
     | 
    
         
            +
            )
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
            opts.each do |opt, arg|
         
     | 
| 
      
 93 
     | 
    
         
            +
              case opt
         
     | 
| 
      
 94 
     | 
    
         
            +
              when "--debug"
         
     | 
| 
      
 95 
     | 
    
         
            +
                require 'pp'
         
     | 
| 
      
 96 
     | 
    
         
            +
                require 'logger'
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                @debug = true
         
     | 
| 
      
 99 
     | 
    
         
            +
                @log = Logger.new(STDERR)
         
     | 
| 
      
 100 
     | 
    
         
            +
                @log.level = Logger::DEBUG
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
              when "--help"
         
     | 
| 
      
 103 
     | 
    
         
            +
                print HELP
         
     | 
| 
      
 104 
     | 
    
         
            +
                exit 0
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
              when '--dnssd'
         
     | 
| 
      
 107 
     | 
    
         
            +
                require 'dnssd'
         
     | 
| 
      
 108 
     | 
    
         
            +
                require 'socket'
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
              when "--browse"
         
     | 
| 
      
 111 
     | 
    
         
            +
                @cmd = :browse
         
     | 
| 
      
 112 
     | 
    
         
            +
                @type   = ARGV.shift
         
     | 
| 
      
 113 
     | 
    
         
            +
                @domain = ARGV.shift || @domain
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
              when "--lookup"
         
     | 
| 
      
 116 
     | 
    
         
            +
                @cmd = :lookup
         
     | 
| 
      
 117 
     | 
    
         
            +
                @name   = ARGV.shift
         
     | 
| 
      
 118 
     | 
    
         
            +
                @type   = ARGV.shift
         
     | 
| 
      
 119 
     | 
    
         
            +
                @domain = ARGV.shift || @domain
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                unless @name && @type
         
     | 
| 
      
 122 
     | 
    
         
            +
                  puts 'name and type required for -L'
         
     | 
| 
      
 123 
     | 
    
         
            +
                  exit 1
         
     | 
| 
      
 124 
     | 
    
         
            +
                end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
              when "--register"
         
     | 
| 
      
 127 
     | 
    
         
            +
                @cmd = :register
         
     | 
| 
      
 128 
     | 
    
         
            +
                @name   = ARGV.shift
         
     | 
| 
      
 129 
     | 
    
         
            +
                @type   = ARGV.shift
         
     | 
| 
      
 130 
     | 
    
         
            +
                @port   = ARGV.shift
         
     | 
| 
      
 131 
     | 
    
         
            +
                if @port.to_i == 0
         
     | 
| 
      
 132 
     | 
    
         
            +
                  @domain = @port
         
     | 
| 
      
 133 
     | 
    
         
            +
                  @port = ARGV.shift.to_i
         
     | 
| 
      
 134 
     | 
    
         
            +
                else
         
     | 
| 
      
 135 
     | 
    
         
            +
                  @port = @port.to_i
         
     | 
| 
      
 136 
     | 
    
         
            +
                end
         
     | 
| 
      
 137 
     | 
    
         
            +
                ARGV.each do |kv|
         
     | 
| 
      
 138 
     | 
    
         
            +
                  kv.match(/([^=]+)=([^=]+)/)
         
     | 
| 
      
 139 
     | 
    
         
            +
                  @txt[$1] = $2
         
     | 
| 
      
 140 
     | 
    
         
            +
                end
         
     | 
| 
      
 141 
     | 
    
         
            +
                ARGV.replace([])
         
     | 
| 
      
 142 
     | 
    
         
            +
              end
         
     | 
| 
      
 143 
     | 
    
         
            +
            end
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
            begin
         
     | 
| 
      
 146 
     | 
    
         
            +
              DNSSD.class
         
     | 
| 
      
 147 
     | 
    
         
            +
              puts "Using native DNSSD..."
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
            	Thread.abort_on_exception = true # So we notice exceptions in DNSSD threads.
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
              module DNSSD
         
     | 
| 
      
 152 
     | 
    
         
            +
                def self.namesplit(n)
         
     | 
| 
      
 153 
     | 
    
         
            +
                  n.scan(/(?:\\.|[^\.])+/)
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
            		# DNSSD > 0.6.0 uses class Reply which has these methods already
         
     | 
| 
      
 156 
     | 
    
         
            +
                class ResolveReply
         
     | 
| 
      
 157 
     | 
    
         
            +
                  def domain
         
     | 
| 
      
 158 
     | 
    
         
            +
                    DNSSD.namesplit(fullname)[-1]
         
     | 
| 
      
 159 
     | 
    
         
            +
                  end
         
     | 
| 
      
 160 
     | 
    
         
            +
                  def type
         
     | 
| 
      
 161 
     | 
    
         
            +
                    DNSSD.namesplit(fullname)[1,2].join('.')
         
     | 
| 
      
 162 
     | 
    
         
            +
                  end
         
     | 
| 
      
 163 
     | 
    
         
            +
                  def name
         
     | 
| 
      
 164 
     | 
    
         
            +
                    DNSSD.namesplit(fullname)[0]
         
     | 
| 
      
 165 
     | 
    
         
            +
                  end
         
     | 
| 
      
 166 
     | 
    
         
            +
                end
         
     | 
| 
      
 167 
     | 
    
         
            +
              end
         
     | 
| 
      
 168 
     | 
    
         
            +
            rescue NameError
         
     | 
| 
      
 169 
     | 
    
         
            +
              require 'net/dns/mdns-sd'
         
     | 
| 
      
 170 
     | 
    
         
            +
              DNSSD = Net::DNS::MDNSSD
         
     | 
| 
      
 171 
     | 
    
         
            +
              Net::DNS::MDNS::Responder.instance.log = @log if @log
         
     | 
| 
      
 172 
     | 
    
         
            +
              puts "Using Net::DNS::MDNSSD..."
         
     | 
| 
      
 173 
     | 
    
         
            +
            end
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
            unless @cmd
         
     | 
| 
      
 176 
     | 
    
         
            +
              print HELP
         
     | 
| 
      
 177 
     | 
    
         
            +
              exit 1
         
     | 
| 
      
 178 
     | 
    
         
            +
            end
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
            case @cmd
         
     | 
| 
      
 181 
     | 
    
         
            +
            when :browse
         
     | 
| 
      
 182 
     | 
    
         
            +
              STDERR.puts( "DNSSD.#{@cmd}(#{@type}, #{@domain}) =>" )  if @debug
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
              fmt = "%-3.3s  %-8.8s   %-15.15s  %-20.20s\n"
         
     | 
| 
      
 185 
     | 
    
         
            +
              printf fmt, "Ttl", "Domain", "Service Type", "Instance Name"
         
     | 
| 
      
 186 
     | 
    
         
            +
             
     | 
| 
      
 187 
     | 
    
         
            +
              handle = DNSSD.browse(@type, @domain) do |reply|
         
     | 
| 
      
 188 
     | 
    
         
            +
                begin
         
     | 
| 
      
 189 
     | 
    
         
            +
                  printf fmt, reply.flags.to_i, reply.domain, reply.type, reply.name
         
     | 
| 
      
 190 
     | 
    
         
            +
                rescue
         
     | 
| 
      
 191 
     | 
    
         
            +
                  p $!
         
     | 
| 
      
 192 
     | 
    
         
            +
                end
         
     | 
| 
      
 193 
     | 
    
         
            +
              end
         
     | 
| 
      
 194 
     | 
    
         
            +
             
     | 
| 
      
 195 
     | 
    
         
            +
              $stdin.gets
         
     | 
| 
      
 196 
     | 
    
         
            +
              handle.stop
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
             
     | 
| 
      
 199 
     | 
    
         
            +
            when :lookup
         
     | 
| 
      
 200 
     | 
    
         
            +
              STDERR.puts( "DNSSD.#{@cmd}(#{@name}, #{@type}, #{@domain}) =>" )  if @debug
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
              fmt = "%-3.3s  %-8.8s   %-19.19s  %-20.20s %-20.20s %s\n"
         
     | 
| 
      
 203 
     | 
    
         
            +
              printf fmt, "Ttl", "Domain", "Service Type", "Instance Name", "Location", "Text"
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
      
 205 
     | 
    
         
            +
              handle = DNSSD.resolve(@name, @type, @domain) do |reply|
         
     | 
| 
      
 206 
     | 
    
         
            +
                begin
         
     | 
| 
      
 207 
     | 
    
         
            +
                  location = "#{reply.target}:#{reply.port}"
         
     | 
| 
      
 208 
     | 
    
         
            +
                  text = reply.text_record.to_a.map { |kv| "#{kv[0]}=#{kv[1].inspect}" }.join(', ')
         
     | 
| 
      
 209 
     | 
    
         
            +
                  printf fmt, reply.flags.to_i, reply.domain, reply.type, reply.name, location, text
         
     | 
| 
      
 210 
     | 
    
         
            +
                rescue
         
     | 
| 
      
 211 
     | 
    
         
            +
                  p $!
         
     | 
| 
      
 212 
     | 
    
         
            +
                end
         
     | 
| 
      
 213 
     | 
    
         
            +
              end
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
              $stdin.gets
         
     | 
| 
      
 216 
     | 
    
         
            +
              handle.stop
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
      
 218 
     | 
    
         
            +
            when :register
         
     | 
| 
      
 219 
     | 
    
         
            +
              STDERR.puts( "DNSSD.#{@cmd}(#{@name}, #{@type}, #{@domain}, #{@port}, #{@txt.inspect}) =>" )  if @debug
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
              fmt = "%-3.3s  %-8.8s   %-19.19s  %-20.20s %-20.20s %s\n"
         
     | 
| 
      
 222 
     | 
    
         
            +
              printf fmt, "Ttl", "Domain", "Service Type", "Instance Name", "Location", "Text"
         
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
      
 224 
     | 
    
         
            +
              handle = DNSSD.register(@name, @type, @domain, @port, @txt) do |notice|
         
     | 
| 
      
 225 
     | 
    
         
            +
                begin
         
     | 
| 
      
 226 
     | 
    
         
            +
                  location = "#{Socket.gethostname}:#{@port}"
         
     | 
| 
      
 227 
     | 
    
         
            +
                  text = @txt.to_a.map { |kv| "#{kv[0]}=#{kv[1].inspect}" }.join(', ')
         
     | 
| 
      
 228 
     | 
    
         
            +
                  printf fmt, 'N/A', notice.domain, notice.type, notice.name, location, text
         
     | 
| 
      
 229 
     | 
    
         
            +
                rescue
         
     | 
| 
      
 230 
     | 
    
         
            +
                  p $!
         
     | 
| 
      
 231 
     | 
    
         
            +
                end
         
     | 
| 
      
 232 
     | 
    
         
            +
              end
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
              $stdin.gets
         
     | 
| 
      
 235 
     | 
    
         
            +
              handle.stop
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
      
 237 
     | 
    
         
            +
            end
         
     | 
| 
      
 238 
     | 
    
         
            +
             
     | 
    
        data/samples/test_dns.rb
    ADDED
    
    | 
         @@ -0,0 +1,128 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/ruby -w
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            $:.unshift File.dirname($0)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require 'net/dns/resolvx.rb'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'test/unit'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            require 'pp'
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            Name = Resolv::DNS::Name
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            class TestDns < Test::Unit::TestCase
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              def test_name_what_I_think_are_odd_behaviours
         
     | 
| 
      
 15 
     | 
    
         
            +
                # Why can't test against strings?
         
     | 
| 
      
 16 
     | 
    
         
            +
                assert_equal(false, Name.create("example.CoM") ==   "example.com")
         
     | 
| 
      
 17 
     | 
    
         
            +
                assert_equal(false, Name.create("example.CoM").eql?("example.com"))
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                # Why does making it absolute mean they aren't equal?
         
     | 
| 
      
 20 
     | 
    
         
            +
                assert_equal(false, Name.create("example.CoM").eql?(Name.create("example.com.")))
         
     | 
| 
      
 21 
     | 
    
         
            +
                assert_equal(false, Name.create("example.CoM") ==   Name.create("example.com."))
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              def test_name_CoMparisons
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                assert_equal(true,  Name.create("example.CoM").eql?(Name.create("example.com")))
         
     | 
| 
      
 27 
     | 
    
         
            +
                assert_equal(true,  Name.create("example.CoM") ==   Name.create("example.com"))
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                assert_equal(true,  Name.create("example.CoM").equal?("example.com."))
         
     | 
| 
      
 30 
     | 
    
         
            +
                assert_equal(true,  Name.create("example.CoM").equal?("example.com"))
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                assert_equal(true,  Name.create("www.example.CoM") <   "example.com")
         
     | 
| 
      
 33 
     | 
    
         
            +
                assert_equal(true,  Name.create("www.example.CoM") <=  "example.com")
         
     | 
| 
      
 34 
     | 
    
         
            +
                assert_equal(-1,    Name.create("www.example.CoM") <=> "example.com")
         
     | 
| 
      
 35 
     | 
    
         
            +
                assert_equal(false, Name.create("www.example.CoM") >=  "example.com")
         
     | 
| 
      
 36 
     | 
    
         
            +
                assert_equal(false, Name.create("www.example.CoM") >   "example.com")
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                assert_equal(false, Name.create("example.CoM") <   "example.com")
         
     | 
| 
      
 39 
     | 
    
         
            +
                assert_equal(true,  Name.create("example.CoM") <=  "example.com")
         
     | 
| 
      
 40 
     | 
    
         
            +
                assert_equal(0,     Name.create("example.CoM") <=> "example.com")
         
     | 
| 
      
 41 
     | 
    
         
            +
                assert_equal(true,  Name.create("example.CoM") >=  "example.com")
         
     | 
| 
      
 42 
     | 
    
         
            +
                assert_equal(false, Name.create("example.CoM") >   "example.com")
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                assert_equal(false, Name.create("CoM") <   "example.com")
         
     | 
| 
      
 45 
     | 
    
         
            +
                assert_equal(false, Name.create("CoM") <=  "example.com")
         
     | 
| 
      
 46 
     | 
    
         
            +
                assert_equal(+1,    Name.create("CoM") <=> "example.com")
         
     | 
| 
      
 47 
     | 
    
         
            +
                assert_equal(true,  Name.create("CoM") >=  "example.com")
         
     | 
| 
      
 48 
     | 
    
         
            +
                assert_equal(true,  Name.create("CoM") >   "example.com")
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                assert_equal(nil,   Name.create("bar.CoM") <   "example.com")
         
     | 
| 
      
 51 
     | 
    
         
            +
                assert_equal(nil,   Name.create("bar.CoM") <=  "example.com")
         
     | 
| 
      
 52 
     | 
    
         
            +
                assert_equal(nil,   Name.create("bar.CoM") <=> "example.com")
         
     | 
| 
      
 53 
     | 
    
         
            +
                assert_equal(nil,   Name.create("bar.CoM") >=  "example.com")
         
     | 
| 
      
 54 
     | 
    
         
            +
                assert_equal(nil,   Name.create("bar.CoM") >   "example.com")
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                assert_equal(nil,   Name.create("net.") <   "com")
         
     | 
| 
      
 57 
     | 
    
         
            +
                assert_equal(nil,   Name.create("net.") <=  "com")
         
     | 
| 
      
 58 
     | 
    
         
            +
                assert_equal(nil,   Name.create("net.") <=> "com")
         
     | 
| 
      
 59 
     | 
    
         
            +
                assert_equal(nil,   Name.create("net.") >=  "com")
         
     | 
| 
      
 60 
     | 
    
         
            +
                assert_equal(nil,   Name.create("net.") >   "com")
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              def test_txt_with_0_strs
         
     | 
| 
      
 65 
     | 
    
         
            +
                # Packet collected from the wild, it is non-conformant with DNS
         
     | 
| 
      
 66 
     | 
    
         
            +
                # specification, TXT record has zero strings, but should have 1 or more.
         
     | 
| 
      
 67 
     | 
    
         
            +
                d = "\000\000\204\000\000\000\000\005\000\000\000\000\002me\005local\000\000\001\200\001\000\000\000\360\000\004\300\250\003\003\005proxy\010_example\004_tcp\300\017\000!\200\001\000\000\000\360\000\010\000\000\000\000'\017\300\f\300$\000\020\200\001\000\000\000\360\000\000\t_services\a_dns-sd\004_udp\300\017\000\f\000\001\000\000\034 \000\002\300*\300*\000\f\000\001\000\000\034 \000\002\300$"
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                m =  Resolv::DNS::Message.decode( d )
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                assert_equal('',    m.answer[2][2].data)
         
     | 
| 
      
 72 
     | 
    
         
            +
                assert_equal([''],  m.answer[2][2].strings)
         
     | 
| 
      
 73 
     | 
    
         
            +
              end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
              def txt_codec(*args)
         
     | 
| 
      
 76 
     | 
    
         
            +
                m = Resolv::DNS::Message.new
         
     | 
| 
      
 77 
     | 
    
         
            +
                m.add_answer('example.local', 0, Resolv::DNS::Resource::IN::TXT.new(*args))
         
     | 
| 
      
 78 
     | 
    
         
            +
            #   pp m
         
     | 
| 
      
 79 
     | 
    
         
            +
                m = Resolv::DNS::Message.decode(m.encode)
         
     | 
| 
      
 80 
     | 
    
         
            +
                txt = m.answer[0][2]
         
     | 
| 
      
 81 
     | 
    
         
            +
            #   pp txt
         
     | 
| 
      
 82 
     | 
    
         
            +
                txt
         
     | 
| 
      
 83 
     | 
    
         
            +
              end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
              def test_txt_with_large_str
         
     | 
| 
      
 86 
     | 
    
         
            +
                # short or no strings
         
     | 
| 
      
 87 
     | 
    
         
            +
                txt = txt_codec()
         
     | 
| 
      
 88 
     | 
    
         
            +
                assert_equal('',   txt.data)
         
     | 
| 
      
 89 
     | 
    
         
            +
                assert_equal([''], txt.strings)
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                txt = txt_codec('')
         
     | 
| 
      
 92 
     | 
    
         
            +
                assert_equal('',   txt.data)
         
     | 
| 
      
 93 
     | 
    
         
            +
                assert_equal([''], txt.strings)
         
     | 
| 
      
 94 
     | 
    
         
            +
                
         
     | 
| 
      
 95 
     | 
    
         
            +
                txt = txt_codec('s')
         
     | 
| 
      
 96 
     | 
    
         
            +
                assert_equal('s',   txt.data)
         
     | 
| 
      
 97 
     | 
    
         
            +
                assert_equal(['s'], txt.strings)
         
     | 
| 
      
 98 
     | 
    
         
            +
                
         
     | 
| 
      
 99 
     | 
    
         
            +
                txt = txt_codec('s', 'a', 'm')
         
     | 
| 
      
 100 
     | 
    
         
            +
                assert_equal('sam',           txt.data)
         
     | 
| 
      
 101 
     | 
    
         
            +
                assert_equal(['s', 'a', 'm'], txt.strings)
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                s = '0' * 255
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                # long strings
         
     | 
| 
      
 106 
     | 
    
         
            +
                txt = txt_codec(s)
         
     | 
| 
      
 107 
     | 
    
         
            +
                assert_equal(s,   txt.data)
         
     | 
| 
      
 108 
     | 
    
         
            +
                assert_equal([s], txt.strings)
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                # long strings
         
     | 
| 
      
 111 
     | 
    
         
            +
                f = s + 'a'
         
     | 
| 
      
 112 
     | 
    
         
            +
                txt = txt_codec(f)
         
     | 
| 
      
 113 
     | 
    
         
            +
                assert_equal(f,   txt.data)
         
     | 
| 
      
 114 
     | 
    
         
            +
                assert_equal([s, 'a'], txt.strings)
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                f = s + s
         
     | 
| 
      
 117 
     | 
    
         
            +
                txt = txt_codec(f)
         
     | 
| 
      
 118 
     | 
    
         
            +
                assert_equal(f,   txt.data)
         
     | 
| 
      
 119 
     | 
    
         
            +
                assert_equal([s, s], txt.strings)
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                assert_raise(ArgumentError) { txt_codec(f, 'a') }
         
     | 
| 
      
 122 
     | 
    
         
            +
                assert_raise(ArgumentError) { txt_codec('a', f) }
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
              end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
            end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
    
        data/samples/v1demo.rb
    ADDED
    
    | 
         @@ -0,0 +1,167 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/local/bin/ruby18 -w
         
     | 
| 
      
 2 
     | 
    
         
            +
            #
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Example code to use the multicast library
         
     | 
| 
      
 4 
     | 
    
         
            +
            # (c) 2005 Ben Giddings
         
     | 
| 
      
 5 
     | 
    
         
            +
            # License: Ruby's License
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            # Include local dir
         
     | 
| 
      
 8 
     | 
    
         
            +
            $: << File.dirname($0)
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            require 'net/dns/resolv-mdns'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require 'pp'
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            # default to browsing
         
     | 
| 
      
 14 
     | 
    
         
            +
            operation = ARGV[0] || 'browse'
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            resolver = Resolv::MDNS.new
         
     | 
| 
      
 17 
     | 
    
         
            +
            resolver.lazy_initialize
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            def usage
         
     | 
| 
      
 20 
     | 
    
         
            +
              $stderr.puts <<-EOF
         
     | 
| 
      
 21 
     | 
    
         
            +
            Usage: #{$0} [browse|discover|resolve|lookup] [service_str]
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            Use "browse" to find names offering the service requested.
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            Examples:
         
     | 
| 
      
 26 
     | 
    
         
            +
              zsh% #{$0} browse
         
     | 
| 
      
 27 
     | 
    
         
            +
              Searching for _http._tcp.local services
         
     | 
| 
      
 28 
     | 
    
         
            +
              Matching entries in _http._tcp.local
         
     | 
| 
      
 29 
     | 
    
         
            +
              Cool Webserver
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              zsh% #{$0} browse http
         
     | 
| 
      
 32 
     | 
    
         
            +
              Searching for _http._tcp.local services
         
     | 
| 
      
 33 
     | 
    
         
            +
              Matching entries in _http._tcp.local
         
     | 
| 
      
 34 
     | 
    
         
            +
              Cool Webserver
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              zsh% #{$0} browse _http._tcp.local
         
     | 
| 
      
 37 
     | 
    
         
            +
              Searching for _http._tcp.local services
         
     | 
| 
      
 38 
     | 
    
         
            +
              Matching entries in _http._tcp.local
         
     | 
| 
      
 39 
     | 
    
         
            +
              Cool Webserver
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              zsh% #{$0} browse _telnet._tcp.local
         
     | 
| 
      
 42 
     | 
    
         
            +
              Searching for _telnet._tcp.local services
         
     | 
| 
      
 43 
     | 
    
         
            +
              Matching entries in _telnet._tcp.local
         
     | 
| 
      
 44 
     | 
    
         
            +
              Embedded Device (MAC addr: 00:01:02:03:04:05)
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            By default 'browse' looks for _http._tcp.local services/
         
     | 
| 
      
 47 
     | 
    
         
            +
            If the only parameter supplied is a protocol, it looks for 
         
     | 
| 
      
 48 
     | 
    
         
            +
            local tcp services of that protocol
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            Use "resolve" to look up the dns name, port and ip address of a device
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              zsh% #{$0} resolve 'Cool Webserver'
         
     | 
| 
      
 53 
     | 
    
         
            +
              Searching for Cool Webserver._http._tcp.local instance
         
     | 
| 
      
 54 
     | 
    
         
            +
              Cool Webserver._http._tcp.local is
         
     | 
| 
      
 55 
     | 
    
         
            +
              coolweb.local:80 at IP 192.168.0.12
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
              zsh% #{$0} resolve 'Cool Webserver._http._tcp.local'
         
     | 
| 
      
 58 
     | 
    
         
            +
              Searching for Cool Webserver._http._tcp.local instance
         
     | 
| 
      
 59 
     | 
    
         
            +
              Cool Webserver._http._tcp.local is
         
     | 
| 
      
 60 
     | 
    
         
            +
              coolweb.local:80 at IP 192.168.0.12
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              zsh% #{$0} resolve 'Embedded Device (MAC addr: 00:01:02:03:04:05)._telnet._tcp.local'
         
     | 
| 
      
 63 
     | 
    
         
            +
              Searching for Embedded Device (MAC addr: 00:01:02:03:04:05)._telnet._tcp.local instance
         
     | 
| 
      
 64 
     | 
    
         
            +
              Embedded Device (MAC addr: 00:01:02:03:04:05)._telnet._tcp.local is
         
     | 
| 
      
 65 
     | 
    
         
            +
              emb000102030405.local:23 at IP 192.168.0.93
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            By default 'resolve' will append _http._tcp.local if it is missing
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
              EOF
         
     | 
| 
      
 70 
     | 
    
         
            +
            end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
            case (operation.downcase)
         
     | 
| 
      
 73 
     | 
    
         
            +
            when 'browse', 'discover'
         
     | 
| 
      
 74 
     | 
    
         
            +
              #
         
     | 
| 
      
 75 
     | 
    
         
            +
              # To browse / discover services, use a ptr lookup on the service protocol
         
     | 
| 
      
 76 
     | 
    
         
            +
              # A typical call might be
         
     | 
| 
      
 77 
     | 
    
         
            +
              # resolver.getresources('_http._tcp.local', Resolv::DNS::Resource::IN::PTR)
         
     | 
| 
      
 78 
     | 
    
         
            +
              #
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
              # default to browsing for http hosts
         
     | 
| 
      
 81 
     | 
    
         
            +
              service_str = ARGV[1] || 'http'
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
              # prepend an underscore if necessary
         
     | 
| 
      
 84 
     | 
    
         
            +
              # p service_str
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
              if ?_ != service_str[0]
         
     | 
| 
      
 87 
     | 
    
         
            +
                puts "prepending underscore to #{service_str}"
         
     | 
| 
      
 88 
     | 
    
         
            +
                service_str = '_' + service_str
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
              # append a ._tcp.local if necessary (assume tcp and local)
         
     | 
| 
      
 92 
     | 
    
         
            +
              if service_str.index('.').nil?
         
     | 
| 
      
 93 
     | 
    
         
            +
                puts "No dot found in service name, appending ._tcp.local"
         
     | 
| 
      
 94 
     | 
    
         
            +
                service_str += '._tcp.local'
         
     | 
| 
      
 95 
     | 
    
         
            +
              end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
              puts "Searching for #{service_str} services"
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
              entries = resolver.getresources(service_str, Resolv::DNS::Resource::IN::PTR)
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
              # p entries
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
              puts "Matching entries in #{service_str}"
         
     | 
| 
      
 104 
     | 
    
         
            +
              entries.each {
         
     | 
| 
      
 105 
     | 
    
         
            +
                |entry|
         
     | 
| 
      
 106 
     | 
    
         
            +
                # p entry
         
     | 
| 
      
 107 
     | 
    
         
            +
                # I think this will always match but just in case...
         
     | 
| 
      
 108 
     | 
    
         
            +
                friendly_name_regexp = /(.*?)\.#{service_str}/
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                match = friendly_name_regexp.match(entry.name.to_s)
         
     | 
| 
      
 111 
     | 
    
         
            +
                if match
         
     | 
| 
      
 112 
     | 
    
         
            +
                  puts match[1]
         
     | 
| 
      
 113 
     | 
    
         
            +
                else
         
     | 
| 
      
 114 
     | 
    
         
            +
                  puts entry.name
         
     | 
| 
      
 115 
     | 
    
         
            +
                end
         
     | 
| 
      
 116 
     | 
    
         
            +
              }
         
     | 
| 
      
 117 
     | 
    
         
            +
            when 'resolve', 'lookup'
         
     | 
| 
      
 118 
     | 
    
         
            +
              #
         
     | 
| 
      
 119 
     | 
    
         
            +
              # To resolve / lookup services, first use a SRV lookup to lookup the service
         
     | 
| 
      
 120 
     | 
    
         
            +
              # details, then extract the hostname from the result.  Using this hostname,
         
     | 
| 
      
 121 
     | 
    
         
            +
              # lookup the A record to find the IP address.
         
     | 
| 
      
 122 
     | 
    
         
            +
              #
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
              service_str = ARGV[1]
         
     | 
| 
      
 125 
     | 
    
         
            +
              if service_str.nil?
         
     | 
| 
      
 126 
     | 
    
         
            +
                $stderr.puts("Service string required for resolve / lookup")
         
     | 
| 
      
 127 
     | 
    
         
            +
                usage()
         
     | 
| 
      
 128 
     | 
    
         
            +
                exit(1)
         
     | 
| 
      
 129 
     | 
    
         
            +
              end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
              # append a ._http._tcp.local if necessary (assume http, tcp and local)
         
     | 
| 
      
 132 
     | 
    
         
            +
              if service_str.index('.').nil?
         
     | 
| 
      
 133 
     | 
    
         
            +
                puts "No dot found in service name, appending ._http._tcp.local"
         
     | 
| 
      
 134 
     | 
    
         
            +
                service_str += '._http._tcp.local'
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
              end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
              puts "Searching for #{service_str} instance"
         
     | 
| 
      
 139 
     | 
    
         
            +
              entries = resolver.getresources(service_str, Resolv::DNS::Resource::IN::SRV)
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
              if 0 == entries.size
         
     | 
| 
      
 142 
     | 
    
         
            +
                puts "Unable to find #{service_str}"
         
     | 
| 
      
 143 
     | 
    
         
            +
                exit(0)
         
     | 
| 
      
 144 
     | 
    
         
            +
              end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
              entry = entries[0]
         
     | 
| 
      
 147 
     | 
    
         
            +
              # puts "Found match at #{entry.target}, port #{entry.port}"
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
              hostname = entry.target
         
     | 
| 
      
 150 
     | 
    
         
            +
              port = entry.port
         
     | 
| 
      
 151 
     | 
    
         
            +
              entries = resolver.getresources(hostname, Resolv::DNS::Resource::IN::A)
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
              if 0 == entries.size
         
     | 
| 
      
 154 
     | 
    
         
            +
                puts "Unable to resolve #{hostname}"
         
     | 
| 
      
 155 
     | 
    
         
            +
                exit(1)
         
     | 
| 
      
 156 
     | 
    
         
            +
              end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
              entry = entries[0]
         
     | 
| 
      
 159 
     | 
    
         
            +
              # p entry
         
     | 
| 
      
 160 
     | 
    
         
            +
              # p entry.address
         
     | 
| 
      
 161 
     | 
    
         
            +
              puts "#{service_str} is\n#{hostname}:#{port} at IP #{entry.address.to_s}"
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
            else
         
     | 
| 
      
 164 
     | 
    
         
            +
              $stderr.puts("unknown operation #{operation.inspect}")
         
     | 
| 
      
 165 
     | 
    
         
            +
              usage()
         
     | 
| 
      
 166 
     | 
    
         
            +
              exit(1)
         
     | 
| 
      
 167 
     | 
    
         
            +
            end
         
     |