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
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_enum(hsh) ⇒ void
abstract
Set enum hash for #type field.
Instance Method Summary collapse
-
#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
-
#value=(val) ⇒ ::String, Integer
abstract
Set
value
.
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.
165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 165 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] end |
Class Attribute Details
.aliases ⇒ Hash
68 69 70 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 68 def aliases @aliases end |
.field_in_length ⇒ Object
72 73 74 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 72 def field_in_length @field_in_length end |
.header_in_length ⇒ Object
70 71 72 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 70 def header_in_length @header_in_length end |
.length ⇒ Integer
Length attribute for real TLV class
|
# File 'lib/packetgen/types/abstract_tlv.rb', line 109
|
.type ⇒ Integer
Type attribute for real TLV class
|
# File 'lib/packetgen/types/abstract_tlv.rb', line 109
|
.value ⇒ Object
Value attribute for real TLV class
|
# File 'lib/packetgen/types/abstract_tlv.rb', line 109
|
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
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 85 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_enum(hsh) ⇒ void
Should only be called on real TLV classes, created by create.
This method returns an undefined value.
Set enum hash for #type field.
123 124 125 126 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 123 def define_type_enum(hsh) field_defs[:type][:enum].clear field_defs[:type][:enum].merge!(hsh) end |
Instance Method Details
#human_type ⇒ String
Should only be called on real TLV class instances.
Get human-readable type
215 216 217 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 215 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
181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 181 def read(str) 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.
221 222 223 224 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 221 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 |
#value=(val) ⇒ ::String, Integer
Should only be called on real TLV class instances.
Set value
. May set length
if value is a String.
197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/packetgen/types/abstract_tlv.rb', line 197 def value=(val) self[:value].from_human(val) 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 val end |