Class: PacketGen::Types::AbstractTLV
- Includes:
- Fieldable
- Defined in:
- lib/packetgen/types/abstract_tlv.rb
Overview
This class is an abstract class to define type-length-value data.
This class supersedes TLV class, which is not well defined on some corner cases.
Usage
To simply define a new TLV class, do:
MyTLV = PacketGen::Types::AbstractTLV.create
MyTLV.define_type_enum 'one' => 1, 'two' => 2
This will define a new MyTLV
class, subclass of Fields. This class will define 3 fields:
.define_type_enum
is, here, necessary to define enum hash to be used for #type
accessor, as this one is defined as an Enum.
This class may then be used as older TLV class:
tlv = MyTLV.new(type: 1, value: 'abcd') # automagically set #length from value
tlv.type #=> 1
tlv.human_type #=> 'one'
tlv.length #=> 4
tlv.value #=> "abcd"
Advanced usage
Each field’s type may be changed at generating TLV class:
MyTLV = PacketGen::Types::AbstractTLV.create(type_class: PacketGen::Types::Int16,
length_class: PacketGen::Types::Int16,
value_class: PacketGen::Header::IP::Addr)
tlv = MyTLV.new(type: 1, value: '1.2.3.4')
tlv.type #=> 1
tlv.length #=> 4
tlv.value #=> '1.2.3.4'
tlv.to_s #=> "\x00\x01\x00\x04\x01\x02\x03\x04"
Some aliases may also be defined. For example, to create a TLV type whose type
field should be named code
:
MyTLV = PacketGen::Types::AbstractTLV.create(type_class: PacketGen::Types::Int16,
length_class: PacketGen::Types::Int16,
aliases: { code: :type })
tlv = MyTLV.new(code: 1, value: 'abcd')
tlv.code #=> 1
tlv.type #=> 1
tlv.length #=> 4
tlv.value #=> 'abcd'
Direct Known Subclasses
Header::DHCP::IPAddrOption, Header::DHCP::Int16Option, Header::DHCP::Int32Option, Header::DHCP::Int8Option, Header::DHCP::Option, Header::DNS::Option, Header::Dot11::Element
Constant Summary collapse
- FIELD_TYPES =
{ 'T' => :type, 'L' => :length, 'V' => :value }.freeze
Class Attribute Summary collapse
- .aliases ⇒ Hash
- .field_in_length ⇒ Object
- .header_in_length ⇒ Object deprecated Deprecated.
- .length ⇒ Integer abstract
- .type ⇒ Integer abstract
- .value ⇒ Object abstract
Instance Attribute Summary collapse
- #length ⇒ Integer abstract
- #type ⇒ Integer abstract
- #value ⇒ Object abstract
Class Method Summary collapse
-
.create(type_class: Int8Enum, length_class: Int8, value_class: String, aliases: {}, header_in_length: false, field_order: 'TLV', field_in_length: 'V') ⇒ Class
Generate a TLV class.
-
.define_type_default(default) ⇒ void
abstract
Set default value for #type field.
-
.define_type_enum(hsh) ⇒ void
abstract
Set enum hash for #type field.
Instance Method Summary collapse
-
#calc_length ⇒ void
Calculate length.
-
#human_type ⇒ String
abstract
Get human-readable type.
-
#initialize(options = {}) ⇒ AbstractTLV
constructor
abstract
A new instance of AbstractTLV.
-
#read(str) ⇒ Fields
abstract
Populate object from a binary string.
- #to_human ⇒ String abstract
Methods included from Fieldable
#format_inspect, #sz, #to_s, #type_name
Methods inherited from Fields
#[], #[]=, #bits_on, define_bit_fields_on, define_field, define_field_after, define_field_before, #fields, fields, inherited, #inspect, #offset_of, #optional?, #optional_fields, #present?, remove_bit_fields_on, remove_field, #sz, #to_h, #to_s, update_field
Constructor Details
#initialize(options = {}) ⇒ AbstractTLV
Should only be called on real TLV classes, created by create.
Returns a new instance of AbstractTLV.
188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 188 def initialize(={}) @header_in_length = self.class.header_in_length @field_in_length = self.class.field_in_length self.class.aliases.each do |al, orig| [orig] = [al] if .key?(al) end super # used #value= defined below, which set length if needed self.value = [:value] if [:value] calc_length unless .key?(:length) end |
Class Attribute Details
.aliases ⇒ Hash
69 70 71 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 69 def aliases @aliases end |
.field_in_length ⇒ Object
73 74 75 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 73 def field_in_length @field_in_length end |
.header_in_length ⇒ Object
71 72 73 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 71 def header_in_length @header_in_length end |
.length ⇒ Integer
Length attribute for real TLV class
|
# File 'lib/packetgen/types/abstract_tlv.rb', line 113
|
.type ⇒ Integer
Type attribute for real TLV class
|
# File 'lib/packetgen/types/abstract_tlv.rb', line 113
|
.value ⇒ Object
Value attribute for real TLV class
|
# File 'lib/packetgen/types/abstract_tlv.rb', line 113
|
Instance Attribute Details
#length ⇒ Integer
Length
|
# File 'lib/packetgen/types/abstract_tlv.rb', line 173
|
#type ⇒ Integer
Type attribute
|
# File 'lib/packetgen/types/abstract_tlv.rb', line 173
|
#value ⇒ Object
Value attribute
|
# File 'lib/packetgen/types/abstract_tlv.rb', line 173
|
Class Method Details
.create(type_class: Int8Enum, length_class: Int8, value_class: String, aliases: {}, header_in_length: false, field_order: 'TLV', field_in_length: 'V') ⇒ Class
Generate a TLV class
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/packetgen/types/abstract_tlv.rb', line 88 def create(type_class: Int8Enum, length_class: Int8, value_class: String, aliases: {}, header_in_length: false, field_order: 'TLV', field_in_length: 'V') Deprecation.deprecated_option(self, 'create', 'header_in_length', klass_method: true) if header_in_length raise Error, '.create cannot be called on a subclass of PacketGen::Types::AbstractTLV' unless self.equal?(AbstractTLV) klass = Class.new(self) klass.aliases = aliases klass.header_in_length = header_in_length klass.field_in_length = field_in_length check_field_in_length(field_in_length) check_field_order(field_order) generate_fields(klass, field_order, type_class, length_class, value_class) aliases.each do |al, orig| klass.instance_eval do alias_method al, orig if klass.method_defined?(orig) alias_method :"#{al}=", :"#{orig}=" if klass.method_defined?(:"#{orig}=") end end klass end |
.define_type_default(default) ⇒ void
137 138 139 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 137 def define_type_default(default) field_defs[:type][:default] = default end |
.define_type_enum(hsh) ⇒ void
127 128 129 130 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 127 def define_type_enum(hsh) field_defs[:type][:enum].clear field_defs[:type][:enum].merge!(hsh) end |
Instance Method Details
#calc_length ⇒ void
This method returns an undefined value.
Calculate length
253 254 255 256 257 258 259 260 261 262 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 253 def calc_length fil = @field_in_length fil = 'TLV' if @header_in_length length = 0 fil.each_char do |field_type| length += self[FIELD_TYPES[field_type]].sz end self.length = length end |
#human_type ⇒ String
Should only be called on real TLV class instances.
Get human-readable type
239 240 241 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 239 def human_type self[:type].to_human.to_s end |
#read(str) ⇒ Fields
Should only be called on real TLV class instances.
Populate object from a binary string
205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 205 def read(str) return self if str.nil? idx = 0 fields.each do |field_name| field = self[field_name] length = field_name == :value ? real_length : field.sz field.read(str[idx, length]) idx += field.sz end self end |
#to_human ⇒ String
Should only be called on real TLV class instances.
245 246 247 248 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 245 def to_human my_value = self[:value].is_a?(String) ? self[:value].inspect : self[:value].to_human 'type:%s,length:%u,value:%s' % [human_type, length, my_value] end |