Module: RubyHome::TLV

Extended by:
TLV
Included in:
TLV
Defined in:
lib/ruby_home/tlv.rb,
lib/ruby_home/tlv/int.rb,
lib/ruby_home/tlv/utf8.rb,
lib/ruby_home/tlv/bytes.rb

Defined Under Namespace

Modules: Bytes, Int, Utf8 Classes: TLV

Constant Summary collapse

TLVs =
[
  TLV.new('00', 'kTLVType_Method', Int),
  TLV.new('01', 'kTLVType_Identifier', Utf8),
  TLV.new('02', 'kTLVType_Salt', Bytes),
  TLV.new('03', 'kTLVType_PublicKey', Bytes),
  TLV.new('04', 'kTLVType_Proof', Bytes),
  TLV.new('05', 'kTLVType_EncryptedData', Bytes),
  TLV.new('06', 'kTLVType_State', Int),
  TLV.new('07', 'kTLVType_Error', Int),
  TLV.new('08', 'kTLVType_RetryDelay', Int),
  TLV.new('09', 'kTLVType_Certificate', Bytes),
  TLV.new('0a', 'kTLVType_Signature', Bytes),
  TLV.new('0b', 'kTLVType_Permissions', Int),
  TLV.new('0c', 'kTLVType_FragmentData', Bytes),
  TLV.new('0d', 'kTLVType_FragmentLast', Bytes),
].freeze

Instance Method Summary collapse

Instance Method Details

#pack(hash) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/ruby_home/tlv.rb', line 25

def pack(hash)
  data = ''

  pack_objects(hash).each do |type, value|
    value.chars.each_slice(510).map(&:join).each do |value_slice|
      length = Int.pack([value_slice].pack('H*').length)

      data << type
      data << length
      data << value_slice
    end
  end

  [data].pack('H*')
end

#pack_objects(objects) ⇒ Object



41
42
43
44
45
46
47
48
# File 'lib/ruby_home/tlv.rb', line 41

def pack_objects(objects)
  objects.each_with_object({}) do |(unpacked_key, unpacked_value), memo|
    tlv_value = TLVs.find { |tlv| tlv.name == unpacked_key }
    packed_key = tlv_value.type
    packed_value = tlv_value.handler.pack(unpacked_value)
    memo[packed_key] = packed_value
  end
end

#unpack(input) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/ruby_home/tlv.rb', line 50

def unpack(input)
  data = input.unpack('H*')[0]
  objects = {}
  scanner_index = 0

  while scanner_index < data.length do
    type = data[scanner_index, 2]
    scanner_index += 2

    byte_length = Int.unpack(data[scanner_index, 2]) * 2
    scanner_index += 2

    newData = data[scanner_index, byte_length]
    if objects[type]
      objects[type] << newData
    else
      objects[type] = newData
    end
    scanner_index += byte_length
  end

  unpack_objects(objects)
end

#unpack_objects(objects) ⇒ Object



74
75
76
77
78
79
80
81
# File 'lib/ruby_home/tlv.rb', line 74

def unpack_objects(objects)
  objects.each_with_object({}) do |(packed_key, packed_value), memo|
    tlv_value = TLVs.find { |tlv| tlv.type == packed_key }
    unpacked_key = tlv_value.name
    unpacked_value = tlv_value.handler.unpack(packed_value)
    memo[unpacked_key] = unpacked_value
  end
end