PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/dnssd/record.rb

http://github.com/tenderlove/dnssd
Ruby | 97 lines | 63 code | 19 blank | 15 comment | 3 complexity | 650a5ef6bdada92d00d50e1b49f8c838 MD5 | raw file
  1. require 'ipaddr'
  2. ##
  3. # Created when adding a DNS record using DNSSD::Service#add_record. Provides
  4. # convenience methods for creating the DNS record.
  5. #
  6. # See also {RFC 1035}[http://www.rfc-editor.org/rfc/rfc1035.txt]
  7. class DNSSD::Record
  8. value_to_name = constants.map do |name|
  9. next if name.intern == :IN
  10. [const_get(name), name.to_s]
  11. end.compact.flatten
  12. ##
  13. # Maps record constant values to the constant name
  14. VALUE_TO_NAME = Hash[*value_to_name]
  15. ##
  16. # Turns +string+ into an RFC-1035 character-string
  17. def self.string_to_character_string(string)
  18. length = string.length
  19. raise ArgumentError, "#{string.inspect} is too long (255 bytes max)" if
  20. length > 255
  21. "#{length.chr}#{string}"
  22. end
  23. ##
  24. # Turns +string+ into an RFC-1035 domain-name
  25. def self.string_to_domain_name(string)
  26. string.split('.').map do |part|
  27. string_to_character_string part
  28. end.join('') << "\0"
  29. end
  30. ##
  31. # Encodes resource +args+ into +type+. Handles:
  32. #
  33. # A AAAA CNAME MX NS PTR SOA SRV TXT
  34. def self.to_data(type, *args)
  35. raise ArgumentError, "unknown type #{type}" unless VALUE_TO_NAME.key? type
  36. data = case type
  37. when A then
  38. addr = args.shift
  39. addr = IPAddr.new addr unless IPAddr === addr
  40. raise ArgumentError, "#{addr} is not IPv4" unless addr.ipv4?
  41. addr.hton
  42. when AAAA then
  43. addr = args.shift
  44. addr = IPAddr.new addr unless IPAddr === addr
  45. raise ArgumentError, "#{addr} is not IPv6" unless addr.ipv6?
  46. addr.hton
  47. when CNAME, NS, PTR then
  48. string_to_domain_name args.shift
  49. when MX then
  50. [args.shift, string_to_domain_name(args.shift)].pack 'na*'
  51. when SOA then
  52. [
  53. string_to_domain_name(args.shift),
  54. string_to_domain_name(args.shift),
  55. args.shift, args.shift, args.shift, args.shift, args.shift
  56. ].pack 'a*a*NNNNN'
  57. when SRV then
  58. [
  59. args.shift, args.shift, args.shift,
  60. string_to_domain_name(args.shift)
  61. ].pack 'nnna*'
  62. when TXT then
  63. data = args.map do |string|
  64. string_to_character_string string
  65. end.join ''
  66. raise ArgumentError,
  67. "TXT record too long (#{data.length} bytes)" if
  68. data.length > 65535
  69. args.clear
  70. data
  71. else
  72. raise ArgumentError, "unhandled record type #{VALUE_TO_NAME[type]}"
  73. end
  74. raise ArgumentError, "Too many arguments for #{VALUE_TO_NAME[type]}" unless
  75. args.empty?
  76. data
  77. end
  78. end