/lib/dnssd/record.rb
Ruby | 97 lines | 63 code | 19 blank | 15 comment | 3 complexity | 650a5ef6bdada92d00d50e1b49f8c838 MD5 | raw file
- require 'ipaddr'
- ##
- # Created when adding a DNS record using DNSSD::Service#add_record. Provides
- # convenience methods for creating the DNS record.
- #
- # See also {RFC 1035}[http://www.rfc-editor.org/rfc/rfc1035.txt]
- class DNSSD::Record
- value_to_name = constants.map do |name|
- next if name.intern == :IN
- [const_get(name), name.to_s]
- end.compact.flatten
- ##
- # Maps record constant values to the constant name
- VALUE_TO_NAME = Hash[*value_to_name]
- ##
- # Turns +string+ into an RFC-1035 character-string
- def self.string_to_character_string(string)
- length = string.length
- raise ArgumentError, "#{string.inspect} is too long (255 bytes max)" if
- length > 255
- "#{length.chr}#{string}"
- end
- ##
- # Turns +string+ into an RFC-1035 domain-name
- def self.string_to_domain_name(string)
- string.split('.').map do |part|
- string_to_character_string part
- end.join('') << "\0"
- end
- ##
- # Encodes resource +args+ into +type+. Handles:
- #
- # A AAAA CNAME MX NS PTR SOA SRV TXT
- def self.to_data(type, *args)
- raise ArgumentError, "unknown type #{type}" unless VALUE_TO_NAME.key? type
- data = case type
- when A then
- addr = args.shift
- addr = IPAddr.new addr unless IPAddr === addr
- raise ArgumentError, "#{addr} is not IPv4" unless addr.ipv4?
- addr.hton
- when AAAA then
- addr = args.shift
- addr = IPAddr.new addr unless IPAddr === addr
- raise ArgumentError, "#{addr} is not IPv6" unless addr.ipv6?
- addr.hton
- when CNAME, NS, PTR then
- string_to_domain_name args.shift
- when MX then
- [args.shift, string_to_domain_name(args.shift)].pack 'na*'
- when SOA then
- [
- string_to_domain_name(args.shift),
- string_to_domain_name(args.shift),
- args.shift, args.shift, args.shift, args.shift, args.shift
- ].pack 'a*a*NNNNN'
- when SRV then
- [
- args.shift, args.shift, args.shift,
- string_to_domain_name(args.shift)
- ].pack 'nnna*'
- when TXT then
- data = args.map do |string|
- string_to_character_string string
- end.join ''
- raise ArgumentError,
- "TXT record too long (#{data.length} bytes)" if
- data.length > 65535
- args.clear
- data
- else
- raise ArgumentError, "unhandled record type #{VALUE_TO_NAME[type]}"
- end
- raise ArgumentError, "Too many arguments for #{VALUE_TO_NAME[type]}" unless
- args.empty?
- data
- end
- end