# Any good tools for reading networking data with optional TLV

**URL:** <https://www.ruby-forum.com/t/any-good-tools-for-reading-networking-data-with-optional-tlv/195952>\
**Category:** Ruby\
**Created:** [October 3, 2010, 9:37pm UTC](https://www.ruby-forum.com/t/any-good-tools-for-reading-networking-data-with-optional-tlv/195952 "2010-10-03T21:37:05Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![rgollamudi](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/b487fb/32.png) [@rgollamudi](https://www.ruby-forum.com/u/rgollamudi)\
**Post date:** [October 3, 2010, 9:37pm UTC](https://www.ruby-forum.com/t/any-good-tools-for-reading-networking-data-with-optional-tlv/195952/1 "2010-10-03T21:37:05Z")

</div>

Hi,

I am trying to write code that reads data off a socket and processes  
that request. This is a proprietary protocol data on UDP. However, the  
packet data that is read contains multiple optional TLVs all of which  
may not exist in all the packets that are read off the socket. The  
existence or non-existence of the TLV in a given data packet is  
indicated by the TLV-type and length in the TLV itself.

Is there a good mechanism available in Ruby to read and handle such  
data. I can do this easily enough in C/C++ but this seems specially hard  
in Ruby. Is the only option pack/unpack methods? I tried to see if  
bindata works but the documentation is unclear on whether it can handle  
multiple TLVS that may exist in different combination in each packet?

Thanks,

Ramana

---

<div class="post-metadata">

**Author:** ![rgollamudi](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/b487fb/32.png) [@rgollamudi](https://www.ruby-forum.com/u/rgollamudi)\
**Post date:** [October 4, 2010, 8:51am UTC](https://www.ruby-forum.com/t/any-good-tools-for-reading-networking-data-with-optional-tlv/195952/2 "2010-10-04T08:51:20Z")

</div>

Ramana Gollamudi wrote:

> I tried to see if bindata works but the documentation is unclear  
> on whether it can handle multiple TLVS that may exist in different  
> combination in each packet?

I am the author of BinData. Yes BinData handles optional TLVs  
(type-length-value). You didn’t specify if your TLVs are nested or  
flat. An example of flat TLVs is given below. Nested TLVs are  
slightly more complicated and require more code so I haven’t provided  
an example. Contact me offlist if you need more details.

Here is an example of a data format (MyFormat) supporting multiple,  
optional, unordered TLVs.

class CustomType1 \< BinData::Record  
int8 :a  
int8 :b  
…  
end

…

class Tlv \< BinData::Record  
endian :big  
uint8 :t  
uint32 :l  
choice :v, :selection =\> :chooser do  
string “unknown”, :read\_length =\> :l  
custom\_type\_1 “v1”  
custom\_type\_2 “v2”  
…  
end

def chooser  
if t == xx and l == yy  
“v1”  
elsif t == ww and l == zz  
…  
else  
“unknown”  
end  
end  
end

class MyFormat \< BinData::Record  
…  
array :options, :type =\> :tlv,  
:read\_until =\> lambda { my\_terminating\_condition }  
end

---

<div class="post-metadata">

**Author:** ![rgollamudi](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/b487fb/32.png) [@rgollamudi](https://www.ruby-forum.com/u/rgollamudi)\
**Post date:** [October 5, 2010, 5:35am UTC](https://www.ruby-forum.com/t/any-good-tools-for-reading-networking-data-with-optional-tlv/195952/3 "2010-10-05T05:35:28Z")

</div>

Dion Mendel wrote:

> Ramana Gollamudi wrote:
> 
> > I tried to see if bindata works but the documentation is unclear  
> > on whether it can handle multiple TLVS that may exist in different  
> > combination in each packet?
> 
> I am the author of BinData. Yes BinData handles optional TLVs  
> (type-length-value). You didn’t specify if your TLVs are nested or  
> flat. An example of flat TLVs is given below. Nested TLVs are  
> slightly more complicated and require more code so I haven’t provided  
> an example. Contact me offlist if you need more details.
> 
> Here is an example of a data format (MyFormat) supporting multiple,  
> optional, unordered TLVs.
> 
> class CustomType1 \< BinData::Record  
> int8 :a  
> int8 :b  
> …  
> end
> 
> …
> 
> class Tlv \< BinData::Record  
> endian :big  
> uint8 :t  
> uint32 :l  
> choice :v, :selection =\> :chooser do  
> string “unknown”, :read\_length =\> :l  
> custom\_type\_1 “v1”  
> custom\_type\_2 “v2”  
> …  
> end
> 
> def chooser  
> if t == xx and l == yy  
> “v1”  
> elsif t == ww and l == zz  
> …  
> else  
> “unknown”  
> end  
> end  
> end
> 
> class MyFormat \< BinData::Record  
> …  
> array :options, :type =\> :tlv,  
> :read\_until =\> lambda { my\_terminating\_condition }  
> end

Dion,

Thanks for clarifying the use of BinData for this. My protocol does not  
have nested TLVs. There are only flat TLVs. The message consists of a  
header and a bunch of different TLVs. The header has an identifier whose  
value identifies the message type. The TLVs are identified by the Type  
field that is the first byte in the TLVs.  
I will try you choice - selection to see if this works.

Thanks,

Ramana
