Class: ReDNS::Name

Inherits:
Fragment show all
Defined in:
lib/redns/name.rb

Constant Summary collapse

POINTER_CHAIN_LIMIT =

Constants ============================================================

64

Instance Attribute Summary

Attributes inherited from Fragment

#attributes

Instance Method Summary collapse

Methods inherited from Fragment

attribute

Methods included from Support

#addr_to_arpa, #bind_all_addr, #default_nameservers, #default_resolver_address, #dns_port, #inet_aton, #inet_ntoa, #io_nonblock, #io_nonblock?, #io_set_nonblock, #is_ip?

Constructor Details

#initialize(contents = nil) ⇒ Name

Instance Methods =====================================================



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/redns/name.rb', line 12

def initialize(contents = nil)
  case (contents)
  when ReDNS::Buffer
    # Ensure that this String subclass is handled using the default
    # method, not intercepted and treated as an actual String
    super(contents)
  when String
    super(name: contents)
    
    unless (ReDNS::Support.is_ip?(name) or self.name.match(/\.\z/))
      self.name += '.'
    end
  else
    super(contents)
  end
end

Instance Method Details

#deserialize(buffer) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/redns/name.rb', line 55

def deserialize(buffer)
  self.name = ''
  
  return_to_offset = nil
  pointer_count = 0

  while (c = buffer.unpack('C')[0])
    if (c & 0xC0 == 0xC0)
      # This is part of a pointer to another section, so advance to that
      # point and read from there, but preserve the position where the
      # pointer was found to leave the buffer in that final state.

      

      # The pointer is encoded as two sequential bytes representing the
      # positional offset.
      if (byte = buffer.unpack('C')[0])
        pointer = (c & 0x3F) << 8 | byte

        return_to_offset ||= buffer.offset
        buffer.rewind
        buffer.advance(pointer)
        
        pointer_count += 1
        
        if (pointer_count > POINTER_CHAIN_LIMIT)
          # Encountered too many pointers, probably a sign of a circular
          # reference or a badly constructed response. Ignore.
          break
        end
      else
        # The buffer may have prematurely run dry, in which case the only
        # option left is to abandon further processing.
        break
      end
    elsif (c == 0)
      break
    else
      if (read = buffer.read(c))
        name << read
        name << '.'
      else
        break
      end
    end
  end
  
  if (return_to_offset)
    buffer.rewind
    buffer.advance(return_to_offset)
  end

  self.name.encode!('UTF-8', undef: :replace, invalid: :replace)
  
  self
end

#empty?Boolean

Returns:

  • (Boolean)


41
42
43
# File 'lib/redns/name.rb', line 41

def empty?
  name == '.'
end

#lengthObject



37
38
39
# File 'lib/redns/name.rb', line 37

def length
  to_s.length
end

#serialize(buffer = ReDNS::Buffer.new) ⇒ Object



45
46
47
48
49
50
51
52
53
# File 'lib/redns/name.rb', line 45

def serialize(buffer = ReDNS::Buffer.new)
  buffer.append(
    self.name.split(/\./).collect { |l| [ l.length, l ].pack("ca*") }.join('')
  )

  buffer.append("\0")
  
  buffer
end

#to_aObject



33
34
35
# File 'lib/redns/name.rb', line 33

def to_a
  [ self.name ]
end

#to_sObject



29
30
31
# File 'lib/redns/name.rb', line 29

def to_s
  self.name
end