Class: Codec::Bertlv

Inherits:
Base
  • Object
show all
Defined in:
lib/codec/tlv.rb

Instance Attribute Summary

Attributes inherited from Base

#id

Instance Method Summary collapse

Methods inherited from Base

#add_sub_codec, #decode_with_length, #encode_with_length, #eval_length, #get_length, #get_sub_codecs

Constructor Details

#initialize(id) ⇒ Bertlv

Returns a new instance of Bertlv.



73
74
75
76
# File 'lib/codec/tlv.rb', line 73

def initialize(id)
  @id = id
  @length = 0
end

Instance Method Details

#build_field(buf, length) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/codec/tlv.rb', line 145

def build_field(buf,length)
  msg = Field.new(@id)
  buffer = buf[0,length]
  while buffer.length > 0
    tag,buffer = tag_decode(buffer)
    f = Field.new(tag)
    value_length,buffer = length_decode(buffer)
    value, buffer = value_decode(buffer,value_length)
	  f.set_value(value)
	  msg.add_sub_field(f)
  end
  return msg
end

#decode(buffer) ⇒ Object



159
160
161
# File 'lib/codec/tlv.rb', line 159

def decode(buffer)
  return build_field(buffer,buffer.length),""
end

#encode(field) ⇒ Object



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/codec/tlv.rb', line 163

def encode(field)
  out = ""
  subfields = field.get_value
  unless subfields.kind_of?(Array)
    raise EncodingException, "Invalid field #{field.to_yaml} for BER Tlv encoding"
  end
  
  while subfields.size > 0
    subfield = subfields.shift
    out += tag_encode(subfield.get_id)
    # TODO : Handle value that is not String
    value = value_encode(subfield.get_value)
    out += length_encode(value.length)
    out += value
  end
  return out
end

#length_decode(buffer) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/codec/tlv.rb', line 101

def length_decode(buffer)
 buf = buffer.dup
 b = buf.slice!(0).getbyte(0)
 if b & 0x80 == 0x80
   # Compute lenght of encoding length sample if first byte is 83 then lenth is encode 
   # on 3 bytes
   loencl = b & 0x7F 
   lb = buf[0,loencl]
   buf = buf[loencl,buf.length]
   length = 0
   while(lb.length > 0)
     length *= 256
	   length += lb.slice!(0).getbyte(0)
   end
   return length,buf
 else
   return b,buf
 end
end

#length_encode(length) ⇒ Object



121
122
123
124
125
126
127
128
129
# File 'lib/codec/tlv.rb', line 121

def length_encode(length)
  out = Numbin.numbin(length,0)
  if out.length > 127
   raise EncodingException,"Invalid length for BER Tlv #{length}"
  elsif out.length > 1
    out = (128 + out.length).chr + out
  end
  return out
end

#tag_decode(buffer) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/codec/tlv.rb', line 78

def tag_decode(buffer)
  buf = buffer.dup
  # removing trailling bytes
  begin ; b = buf.slice!(0).getbyte(0) ; end while (b == 0 || b == 255)
  tag = b.chr
  if (b & 0x1F == 0x1F) 
    begin 
      nb = buf.slice!(0).getbyte(0)
	    tag += nb.chr
	  end while nb & 0x80 == 0x80
  end
  return tag.unpack("H*").first.upcase, buf
end

#tag_encode(tag) ⇒ Object



92
93
94
95
96
97
98
99
# File 'lib/codec/tlv.rb', line 92

def tag_encode(tag)
  buf = [tag].pack("H*")
  check_tag, remain = tag_decode(buf)
  if tag != check_tag || remain != ""
    raise EncodingException, "Invalid BER tag [#{tag}]"
  end
  return buf
end

#value_decode(buf, length) ⇒ Object



131
132
133
134
135
136
137
138
139
# File 'lib/codec/tlv.rb', line 131

def value_decode(buf,length)
  if length > buf.length
    raise ErrorBufferUnderflow,"Not enough data for parsing BER TLV 
       #{@id} length value #{length} remaining only #{buf.length}"
  end
  value = buf[0,length]
  buf = buf[length,buf.length]
  return value.unpack("H*").first.upcase,buf
end

#value_encode(unpack_buffer) ⇒ Object



141
142
143
# File 'lib/codec/tlv.rb', line 141

def value_encode(unpack_buffer)
  [unpack_buffer].pack("H*")
end