Module: RobotLab::Discovery::TxtRecord

Defined in:
lib/robot_lab/discovery/txt_record.rb

Constant Summary collapse

PATH_KEY =

Short wire keys — every byte saved is more room for capability names. p = path (vs "path=" — saves 3 bytes) v = rl_version (vs "rl_version=" — saves 9 bytes) c = capabilities (vs "capabilities=" — saves 11 bytes)

"p"
VERSION_KEY =
"v"
CAPABILITIES_KEY =
"c"
MAX_STRING_BYTES =

RFC 1035 §3.3.14: each string in a TXT record is length-prefixed with one byte, so the content of any single string is capped at 255 bytes.

255
MAX_TOTAL_BYTES =

mDNS runs over UDP. Ethernet MTU (1500) minus IP/UDP/DNS headers leaves ~1472 bytes for the DNS payload. After accounting for the SRV, A/AAAA, and PTR records that accompany a service announcement, the TXT record wire size (1 length-prefix byte per string + content bytes) should stay under 1300 bytes to fit in a single unfragmented packet.

1300
MAX_CAPABILITIES_CONTENT =

Bytes available for capability names + commas after key + "=" overhead.

MAX_STRING_BYTES - CAPABILITIES_KEY.bytesize - 1

Class Method Summary collapse

Class Method Details

.decode(strings) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/robot_lab/discovery/txt_record.rb', line 38

def self.decode(strings)
  strings.each_with_object({}) do |entry, hash|
    k, v = entry.split("=", 2)
    next unless k && v
    case k
    when PATH_KEY         then hash[:path]         = v
    when VERSION_KEY      then hash[:rl_version]   = v
    when CAPABILITIES_KEY then hash[:capabilities] = v.split(",")
    end
  end
end

.encode(path:, capabilities: []) ⇒ Object

253



28
29
30
31
32
33
34
35
36
# File 'lib/robot_lab/discovery/txt_record.rb', line 28

def self.encode(path:, capabilities: [])
  record = [
    "#{PATH_KEY}=#{path}",
    "#{VERSION_KEY}=#{VERSION}"
  ]
  record << "#{CAPABILITIES_KEY}=#{Array(capabilities).join(",")}" unless Array(capabilities).empty?
  validate!(record)
  record
end

.validate!(strings) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/robot_lab/discovery/txt_record.rb', line 50

def self.validate!(strings)
  strings.each do |s|
    next unless s.bytesize > MAX_STRING_BYTES
    raise Error,
          "TXT record string exceeds #{MAX_STRING_BYTES} bytes " \
          "(#{s.bytesize} bytes): #{s[0, 40].inspect}#{"..." if s.length > 40}"
  end

  # Wire size: each string occupies 1 length-prefix byte + its content.
  wire_size = strings.sum { |s| 1 + s.bytesize }
  if wire_size > MAX_TOTAL_BYTES
    raise Error,
          "TXT record wire size exceeds #{MAX_TOTAL_BYTES} bytes (#{wire_size} bytes). " \
          "Shorten path or reduce the number/length of capabilities."
  end

  strings
end