class Diameter::AVP
Represents a Diameter
AVP
. Use this for non-vendor-specific AVPs, and its subclass VendorSpecificAVP for ones defined for a particular vendor. @!attribute [r] code
@return [Fixnum] The AVP Code
@!attribute [r] mandatory
@return [true, false] Whether this AVP is mandatory (i.e. its M flag is set)
Attributes
Public Class Methods
Creates an AVP
by name, and assigns it a value.
@param name The name of the AVP
, e.g. “Origin-Host” @param val The value of the AVP
. Must be of the type defined for
that AVP - e.g. a Fixnum for an AVP defined as Unsigned32, a String for an AVP defined as OctetString, or an IPAddr for an AVP defined as IPAddress.
@option opts [true, false] mandatory
Whether understanding this AVP is mandatory within this application.
@return [AVP] The AVP
that was created.
# File lib/diameter/avp.rb, line 77 def self.create(name, val, options = {}) code, type, vendor = AVPNames.get(name) options[:vendor_id] = vendor avp = AVP.new(code, options) set_content(avp, type, val) avp end
Defines a new AVP
that can subsequently be created/retrieved by name.
@param name [String] The AVP
name @param code [Fixnum] The AVP
Code @param type [AVPType] The type of this AVP's value @param vendor [Fixnum] Optional vendor ID for a vendor-specific
AVP.
@return [void]
# File lib/diameter/avp.rb, line 96 def self.define(name, code, type, vendor=nil) AVPNames.add(name, code, type, vendor) end
@api private
Prefer {AVP.create} where possible.
# File lib/diameter/avp.rb, line 58 def initialize(code, options = {}) @code = code @vendor_id = options[:vendor_id] || 0 @content = options[:content] || '' @mandatory = options.fetch(:mandatory, true) end
Private Class Methods
@!endgroup
# File lib/diameter/avp.rb, line 355 def self.set_content(avp, type, val) case type when Grouped avp.grouped_value = val when OctetString avp.octet_string = val when Unsigned32 avp.uint32 = val when Unsigned64 avp.uint64 = val when Integer32 avp.int32 = val when Integer64 avp.int64 = val when Float32 avp.float32 = val when Float64 avp.float64 = val when IPAddress avp.ip_address = val end end
Public Instance Methods
Returns this AVP's byte data, interpreted as a Float32.
@return [Float] The contained Float32.
# File lib/diameter/avp.rb, line 300 def float32 @content.unpack('g')[0] end
Sets this AVP's byte data to a Float32.
@param [Float] value @return [void]
# File lib/diameter/avp.rb, line 308 def float32=(value) @content = [value].pack('g') end
Returns this AVP's byte data, interpreted as a Float64.
@return [Float] The contained Float64.
# File lib/diameter/avp.rb, line 315 def float64 @content.unpack('G')[0] end
Sets this AVP's byte data to a Float64.
@param [Float] value @return [void]
# File lib/diameter/avp.rb, line 323 def float64=(value) @content = [value].pack('G') end
Returns this AVP's byte data, interpreted as a {tools.ietf.org/html/rfc6733#section-4.4 Grouped AVP}.
@return [Array<AVP>] The contained AVPs.
# File lib/diameter/avp.rb, line 169 def grouped_value AVPParser.parse_avps_int(@content) end
Sets this AVP's byte data to a {tools.ietf.org/html/rfc6733#section-4.4 Grouped AVP}.
@param [Array<AVP>] avps The AVPs that should be contained within
this AVP.
@return [void]
# File lib/diameter/avp.rb, line 179 def grouped_value=(avps) new_content = '' avps.each { |a| new_content += a.to_wire } @content = new_content end
For a grouped AVP
, returns the first AVP
with this name it contains.
@param [String] name The AVP
name @return [AVP] if this AVP
is found inside the Grouped AVP
@return [nil] if this AVP
is not found inside the Grouped AVP
# File lib/diameter/avp.rb, line 191 def inner_avp(name) avps = inner_avps(name) if avps.empty? nil else avps[0] end end
Returns this AVP's byte data, interpreted as an Integer32.
@return [Fixnum] The contained Integer32.
# File lib/diameter/avp.rb, line 240 def int32 @content.unpack('l>')[0] end
Sets this AVP's byte data to an Integer32.
@param [Fixnum] value @return [void]
# File lib/diameter/avp.rb, line 248 def int32=(value) @content = [value].pack('l>') end
Returns this AVP's byte data, interpreted as an Integer64.
@return [Fixnum] The contained Integer64.
# File lib/diameter/avp.rb, line 255 def int64 @content.unpack('q>')[0] end
Sets this AVP's byte data to an Integer64.
@param [Fixnum] value @return [void]
# File lib/diameter/avp.rb, line 263 def int64=(value) @content = [value].pack('q>') end
Returns this AVP's byte data, interpreted as an {tools.ietf.org/html/rfc6733#section-4.3.1 Address}.
@return [IPAddr] The contained
{http://tools.ietf.org/html/rfc6733#section-4.3.1 Address}.
# File lib/diameter/avp.rb, line 332 def ip_address IPAddr.new_ntoh(@content[2..-1]) end
Sets this AVP's byte data to an Address.
@param [IPAddr] value @return [void]
# File lib/diameter/avp.rb, line 340 def ip_address=(value) bytes = if value.ipv4? [1].pack('n') else [2].pack('n') end bytes += value.hton @content = bytes end
Returns this AVP's byte data, interpreted as an OctetString.
@return [String] The contained OctetString.
# File lib/diameter/avp.rb, line 223 def octet_string @content end
Sets this AVP's byte data to an OctetString.
@param [String] value The octets to use as the value. @return [void]
# File lib/diameter/avp.rb, line 231 def octet_string=(value) @content = value end
Returns a string representation of this AVP
. Makes a best-effort attempt to guess the type of the content (even for unknown AVPs) and display it sensibly.
@example
avp.to_s => "AVP 267, mandatory: true, content as int32: 1"
# File lib/diameter/avp.rb, line 128 def to_s has_all_ascii_values = @content.bytes.reject { |c| (32 < c && c < 126) }.empty? could_be_32bit_num = (@content.length == 4) could_be_64bit_num = (@content.length == 8) could_be_ip = ((@content.length == 6 && @content[0..1] == "\x00\x01") || (@content.length == 18 && @content[0..1] == "\x00\x02")) maybe_grouped = !(has_all_ascii_values || could_be_64bit_num || could_be_32bit_num || could_be_ip) s = vendor_specific? ? "AVP #{@code}, Vendor-ID #{@vendor_id}, mandatory: #{@mandatory}" : "AVP #{@code}, mandatory: #{@mandatory}" s += ", content as string: #{@content}" if has_all_ascii_values s += ", content as int32: #{uint32}" if could_be_32bit_num s += ", content as int64: #{uint64}" if could_be_64bit_num s += ", content as ip: #{ip_address}" if could_be_ip s += ", grouped AVP, #{grouped_value.collect(&:to_s)}" if maybe_grouped s end
Returns this AVP
encoded properly as bytes in network byte order, suitable for sending over a TCP or SCTP connection. See {tools.ietf.org/html/rfc6733#section-4.1} for the format.
@return [String] The bytes representing this AVP
# File lib/diameter/avp.rb, line 106 def to_wire if vendor_specific? to_wire_vendor else to_wire_novendor end end
Returns this AVP's byte data, interpreted as an Unsigned32.
@return [Fixnum] The contained Unsigned32.
# File lib/diameter/avp.rb, line 270 def uint32 @content.unpack('N')[0] end
Sets this AVP's byte data to an Unsigned32.
@param [Fixnum] value @return [void]
# File lib/diameter/avp.rb, line 278 def uint32=(value) @content = [value].pack('N') end
Returns this AVP's byte data, interpreted as an Unsigned64.
@return [Fixnum] The contained Unsigned64.
# File lib/diameter/avp.rb, line 285 def uint64 @content.unpack('Q>')[0] end
Sets this AVP's byte data to an Unsigned64.
@param [Fixnum] value @return [void]
# File lib/diameter/avp.rb, line 293 def uint64=(value) @content = [value].pack('Q>') end
@!attribute [r] vendor_specific?
@return [true, false] Whether this AVP is mandatory (i.e. its M flag is set)
# File lib/diameter/avp.rb, line 159 def vendor_specific? @vendor_id != 0 end
Protected Instance Methods
# File lib/diameter/avp.rb, line 394 def padded_content wire_content = @content wire_content += "\x00" while ((wire_content.length % 4) != 0) wire_content end
Private Instance Methods
# File lib/diameter/avp.rb, line 378 def to_wire_novendor length_8, length_16 = UInt24.to_u8_and_u16(@content.length + 8) avp_flags = @mandatory ? '01000000' : '00000000' header = [@code, avp_flags, length_8, length_16].pack('NB8Cn') header + padded_content end
# File lib/diameter/avp.rb, line 385 def to_wire_vendor length_8, length_16 = UInt24.to_u8_and_u16(@content.length + 12) avp_flags = @mandatory ? '11000000' : '10000000' header = [@code, avp_flags, length_8, length_16, @vendor_id].pack('NB8CnN') header + padded_content end