Module: AVPParser

Included in:
AVP
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

+ (true, false) mandatory_bit(flags)

Is the mandatory bit (the second bit) set?

Parameters:

  • flags (String)

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

Returns:

  • (true, false)


20
21
22
# File 'lib/diameter/avp_parser.rb', line 20

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

+ (Array<AVP>) parse_avps_int(bytes)

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.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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
# File 'lib/diameter/avp_parser.rb', line 28

def self.parse_avps_int(bytes)
  avps = []
  position = 0
  while position < bytes.length
    # Consume the first 8 octets
    first_avp_header = bytes[position..position + 8]
    position += 8

    # Parse them
    code, avp_flags, alength_8, alength_16 = first_avp_header.unpack('NB8Cn')

    length = UInt24.from_u8_and_u16(alength_8, alength_16)

    # Default values in the case where this isn't vendor-specific
    avp_consumed = 8
    avp_vendor = 0

    # If this is vendor-specific, read the vendor ID
    if vendor_id_bit(avp_flags)
      avp_vendor_header = bytes[position..position + 4]
      position += 4
      avp_vendor, = avp_vendor_header.unpack('N')
      avp_consumed = 12
    end

    # 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 =
      if vendor_id_bit(avp_flags)
        VendorSpecificAVP.new(code,
                              avp_vendor,
                              mandatory: mandatory_bit(avp_flags),
                              content: avp_content)
      else
        AVP.new(code,
                mandatory: mandatory_bit(avp_flags),
                content: avp_content)
      end
    avps.push parsed_avp
  end
  avps
end

+ (true, false) vendor_id_bit(flags)

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

Parameters:

  • flags (String)

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

Returns:

  • (true, false)


12
13
14
# File 'lib/diameter/avp_parser.rb', line 12

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