Pregunta

I need to convert one C structure into TLV format and send it across. Can someone help me with same? My structure is a really nested structure with lot of in-directions (pointers) to different structures and lot of void *. So, i am stuck and could use help.

struct a {    
    char a[100];    
    char b;    
    struct b *tag;    
    struct c *value;    
    void *data;    
};

struct b {    
    void *data;    
    int a;    
};

struct c {    
    void *data;    
    char arr[100];    
};
¿Fue útil?

Solución

TLV stands for Tag Length Value, and that's exactly what it is. You might have some confusion on this point. Normal usage of this is when you get a large buffer of bytes, perhaps being filled from some serial device, and you need to know what is in that buffer.

Take for example the communication between a SIM card and a phone. There are a number of well defined Tags each corresponding to a type of message that will be decoded. (These are all defined in specification such as ISO 7816-4) and for example if you want to write to a binary file in the SIM card you need to tell the SIM card how many bytes of data you want to send it. So you'd construct some message like:

   A0 D0 00 00 0A 01 02 03 04 05 06 07 08 09 0A 
  +-----+     +-+ +---------------------------+
     |         |              |
    tag     length          Value

// A0D0 - the tag tells the SIM I want to "write a binary file to a GSM SIM card"
// 0A -   Says the aforementioned write will be 10 bytes in Length
// 0102... - Then the Value follows the length 

So in this case we used TLV to send a buffer full of bytes, the receiving device (SIM card in this case) will parse the Tag, known to expect the Length then know how many bytes of "Value" are coming before the transmission is complete. Note this isn't a full true TLV because each piece of data doesn't have it's own TL some are just known (such as those 00's between the "tag" and "length", those are parameters and they're set to be 1 byte and always follow the instruction is it's not needed to have a tag or length)

So that's the overview. Now where does that leave us with your issue? First, as I hope you can see now, we need to know what is going to be Tagged. That depends on who is expecting the data, this is something you should know. Looking at your problem I'd think it was something like this:

  1. Client A generates a "struct a" to send to client B. (There must be a "struct a" tag)
  2. "struct a" is comprised of "struct b" and "struct c" so we need tags of these as well

In order of Client B to be able to read these values we need to define the Tags:

// Tags for structures
#define TAG_A 0x90       // These values are made up but it's important to note
#define TAG_B 0x91       // both Client A and Client B must know what the tags mean
#define TAG_C 0x92       // what what value they are set to

Ideally since you have embedded data within each structure you would have sub tags as well:

// Tags for struct A:
#define TAG_A_FIX_DATA 0x93
#define TAG_A_VAR_DATA 0x94
#define TAG_B_FIX_DATA 0x95
#define TAG_B_VAR_DATA 0x96

So each of your structs would be filled with data as normal then when you go to send the data you'd deconstruct the values into a buffer. The following pseudo code gives you the idea

unsigned char *buffer = malloc(/*big enough for struct a+b+c+tags*/);
buffer[0] = TAG_A;
buffer[1] = /*size of your A structure*/
buffer[2] = TAG_A_FIX_DATA;
buffer[3] = 101; // for the array and the char.. if that's how you want to handle it
buffer[4-105] = a.a and a.b;
buffer[106] = TAG_B;
buffer[107] = /*length of struct B*/
...

So when Client B gets the large buffer of data they can construct their own local struct a, struct b, and struct c then parse out the fields and populate.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top