Module: Diameter::Internals::AVPParser

Defined in:
lib/diameter/avp_parser.rb

Overview

Parser mixin, sharing functionality common to:

* parsing all the AVPs in a message
* parsing the AVPs inside a Grouped AVP

Class Method Summary collapse

Class Method Details

.mandatory_bit(flags) ⇒ true, false

Is the mandatory bit (the second bit) set?

Parameters:

  • flags (String)

    A string of eight bits, e.g. “00000000”

Returns:

  • (true, false)


22
23
24
# File 'lib/diameter/avp_parser.rb', line 22

def self.mandatory_bit(flags)
  flags[1] == '1'
end

.parse_avp_header(bytes) ⇒ Array(Fixnum, Fixnum, Bool, Fixnum, Fixnum)

(8 or 12), AVP code, mandatory bit, length and vendor-ID (or 0 in the case of a non-vendor-specific AVP).

Returns:

  • (Array(Fixnum, Fixnum, Bool, Fixnum, Fixnum))

    The bytes consumed



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/diameter/avp_parser.rb', line 30

def self.parse_avp_header(bytes)
  first_avp_header = bytes[0..8]
  # Parse them
  code, avp_flags, alength_8, alength_16 =
    first_avp_header.unpack('NB8Cn')
  
  mandatory = mandatory_bit(avp_flags)
  length = UInt24.from_u8_and_u16(alength_8, alength_16)

  if vendor_id_bit(avp_flags)
    avp_vendor_header = bytes[8..12]
    avp_vendor, = avp_vendor_header.unpack('N')
    [12, code, mandatory, length, avp_vendor]
  else
    [8, code, mandatory, length, 0]
  end
end

.parse_avps_int(bytes) ⇒ Array<AVP>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns The AVPs parsed out of the bytes.

Parameters:

  • bytes (String)

    A sequence of bytes representing a set of AVPs.

Returns:

  • (Array<AVP>)

    The AVPs parsed out of the bytes.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/diameter/avp_parser.rb', line 52

def self.parse_avps_int(bytes)
  avps = []
  position = 0
  while position < bytes.length
    # Consume the first 8 octets
    avp_consumed, code, mandatory, length, avp_vendor = parse_avp_header(bytes[position..-1])
    position += avp_consumed

    # Read the content, ensuring it aligns to a 32-byte boundary
    avp_content_length = length - avp_consumed
    avp_content = bytes[position..(position + avp_content_length) - 1]

    padding = 0
    padding += 1 until ((avp_content_length + padding) % 4) == 0

    position += avp_content_length + padding

    # Construct an AVP object from the parsed data
    parsed_avp = AVP.new(code,
                         vendor_id: avp_vendor,
                         mandatory: mandatory,
                         content: avp_content)

    avps.push parsed_avp
  end
  avps
end

.vendor_id_bit(flags) ⇒ true, false

Is the vendor-specific bit (the top bit) set?

Parameters:

  • flags (String)

    A string of eight bits, e.g. “00000000”

Returns:

  • (true, false)


14
15
16
# File 'lib/diameter/avp_parser.rb', line 14

def self.vendor_id_bit(flags)
  flags[0] == '1'
end