Skip to content

Small C++ library to facilitate extracting (parsing) and accessing the data from packets of a fixed format.

Notifications You must be signed in to change notification settings

formiaczek/packet_handling

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

packet_handling

This is a small library originally written to facilitate access to the data serialized in packets of a fixed size. Providing a high-level interface it can be used for serializing any data.

In some ways it is similar to google protocol buffers (https://developers.google.com/protocol-buffers/)

but:

  • it is a C++ library, so it gets compiled with your program

  • the format / layout of the data is defined dynamically (no need to generate the it for a given format)

  • the actual data in the buffer does not contain any additional information - this information is only held by the Packet object. Packet is really like a 'template', or a 'parser', that facilitates accessing various fields of the data.

  • it can be useful when implementing protocols giving an easy interface to define data structures.

  • down side is that format has to be known at both sides:

    • when reading / writing the data unless(*)...
  • (*)TODO: perhaps could add some code to create/handle a header, containing all format information needed to build a packet. This header could then be stored/transmitted and used to re-create a Packet at the 'reception' side?

Refer to in-source documentation and examples for more information.

/* Example:
 Example packet (Initialise Data Source-Packet I.D. 128
 for the GPS protocol) (message sent over serial port):

 Name                 Bytes     Units
 0    Packet ID       1
 1    ECEF X          4        Meters
 2    ECEF Y          4        Meters
 3    ECEF Z          4        Meters
 4    Clock Offset    4        Hz
 5    Time of Week    4        Seconds
 6    Week Number     2
 7    Channels        1
 8    Reset Config    1

 Could be defined as follows:
 @code
 uint8_t* buffer = new uint8_t[25];
 Packet gps_id_128(buffer, 25);

 gps_id_128.add_field<uint8_t> ("Packet ID");
 gps_id_128.add_field<uint32_t>("ECEF X");
 gps_id_128.add_field<uint32_t>("ECEF Y");
 gps_id_128.add_field<uint32_t>("ECEF Z");
 gps_id_128.add_field<uint32_t>("Clock Offset");
 gps_id_128.add_field<uint32_t>("Time of Week");
 gps_id_128.add_field<uint16_t>("Week Number");
 gps_id_128.add_field<uint8_t> ("Channels");
 gps_id_128.add_field<uint8_t> ("Reset Config");

 // from now on, these fields can be accessed either by the name:
 gps_id_128.set_field("Time of Week", 0xffeb3fe3); // to set the field.

 // or by id:
 gps_id_128.set_field(7, 2); // id == 7 for channels
 gps_id_128.set_field(1, 2); // id == 2 for ECEF X

 std::cout << gps_id_128 << "\n"; // can also print it out..
/* Example output:

 GPS 128, total size: 0x19 :

 Packet ID    : 0
 ECEF X       : 0x2
 ECEF Y       : 0
 ECEF Z       : 0
 Clock Offset : 0
 Time of Week : 0xffeb3fe3
 Week Number  : 0
 Channels     : 0x2
 Reset Config : 0
 */

Another example (multiple level of packets):

    /* packet created as follows: */
    Packet all(buffer, total_size);
    all.set_name("Flat data packet");
    all.add_field<char*> ("payload", all.bytes_left()); // create one field only with remaining space

    // packet is just a way of interpreting / using the data- there could be more packetso
    // to interpret the same buffer
    Packet car(buffer, total_size);
    car.set_name("CAR");

    car.add_field<char*>("make", 9); // 9 bytes for make
    car.add_field<char*>("model", 9);

    car.add_field<int>("prod_year");
    car.add_field<char*>("engine", 27);

    // can add sub-packets within ptr fields:
    Packet& engine = car.sub_packet("engine");
    engine.add_field<char*>("type", 8);
    engine.add_field<char*>("fuel", 8);
    engine.add_field<char*>("version", 3);

    engine.add_field<char*>("params", 6); // 6 bytes for params
    Packet& engine_params = engine.sub_packet("params");
    engine_params.add_field<short>("ps");
    engine_params.add_field<short>("top speed mph");
    engine_params.add_field<short>("cylinders");

    // accessing fields
    car.set_field("make", "Porshe", sizeof("Porshe"));
    car.set_field("model", "911 GT1", sizeof("911 GT1"));
    car.set_field("prod_year", 2008);

    engine_params.set_field("cylinders", 6);
    engine_params.set_field("top speed mph", 191);

    // can also access sub-packets by traversing from the root..
    car.sub_packet("engine").set_field("fuel", "Ethanol", 7);
    car.sub_packet("engine").set_field("type", "flat-6", 6);

    car.sub_packet("engine").sub_packet("params").set_field("ps", 544);

// could be printed as follows:
std::cout << "\n" << car << "\n";

/* output:

CAR, total size: 0x31 :
make      : (size 0x9): 50 6f 72 73 68 65 00 00 00                        Porshe...
model     : (size 0x9): 39 31 31 20 47 54 31 00 00                        911 GT1..
prod_year : 0x7d8
engine    : (size 0x1b):
  type        : (size 0x8): 66 6c 61 74 2d 36 00 00                           flat-6..
  fuel        : (size 0x8): 45 74 68 61 6e 6f 6c 00                           Ethanol.
  version     : (size 0x3): 00 00 00                                          ...
  params      : (size 0x6):
    ps                    : 0x220
    top speed mph         : 0xbf
    cylinders             : 0x6
*/


std::cout << all << "\n"; // print the whole payload data..

/* output:

Flat data packet, total size: 0x36 :
payload : (size 0x36):
                       50 6f 72 73 68 65 00 00 00 39 31 31 20 47 54 31   Porshe...911 GT1
                       00 00 d8 07 00 00 66 6c 61 74 2d 36 00 00 45 74   ......flat-6..Et
                       68 61 6e 6f 6c 00 00 00 00 20 02 bf 00 06 00 00   hanol.... ......
                       00 00 00 00 00 00                                 ......
 */

// or in JSON:
car.to_json(std::cout);

/* output:
{"name": "CAR", "total_size": 49, "fields": ["make": "Porshe", "model": "911 GT1", "prod_year": 2008, "engine": {"fields": ["type": "flat-6", "fuel": "Ethanol", "version": "", "params": {"fields": ["ps": 544, "top speed mph": 191, "cylinders": 6]}]}]}
*/

About

Small C++ library to facilitate extracting (parsing) and accessing the data from packets of a fixed format.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published