Design pattern for message packet header - c++

I am writing my own messaging API using libevent. The data is wrapped by a packet structure which contains a packet body of data byte array and a packet header that contains the entire packet size information (for the reason to invoke callback at a complete stream).
class PacketHeader {
size_t packet_size;
};
class Packet {
PacketHeader header;
uint8_t* body;
};
However, I wanna users be able to customize their own PacketHeader, while I can handle the underlying size information for messaging. What is the best practice to do this? Should I use inheritance or pure virtual abstraction (interface class). I was thinking about the following but not sure if it is the best practice.
template <class Derived>
class PacketHeader{
size_t packet_size;
size_t header_size() const {return sizeof(Derived);}
}

Instead of all the inheritance stuff, why not make the packets self describing, i.e. something like:
struct packet_header {
int16_t size; // size_t is too big
uint8_t header; // header size
uint8_t type; // header type, some sort of id for header/message
};
Then users can define their own header types with sizes, a message would be composed as follows:
[ ][ ][ ]<--custom header-->[--body--]
So the custom header block is optional and the size is specified in the packet header. Then allow user specific code to decode the header appropriately.

Related

Is there a guaranteed way to avoid padding between base and derived class?

I'm working on a network program that will deal with packets having a header portion and a payload portion. The header is variable-length, with extension segments added or removed depending on network conditions. The user data portion is a plain byte buffer, although it may be treated as some sort of structure or other during packet construction or use.
I would like to have a base class that builds & manipulates the header, with the header bytes (possibly) shifted forwards or backwards if necessary to insert an extension field, and a derived class containing the user data. For example:
class hdr {
public:
const void *start( void ) { return uint8_t(pBuf) + sizeof(pBuf) - SIZEOF_HEADER - pExtBytes; }
private:
size_t pExtBytes;
uint32_t pBuf[16]; // header data goes here, shifted to the END of the buffer, adjacent the beginning of the derived class
// NO PADDING HERE!
} ;
class payload1 : public hdr {
public:
private:
uint8_t pData[128];
} ;
class payload2 : public hdr {
public:
private:
uint16_t pData[12];
} ;
Is there a standard way to guarantee that there's no padding between hdr and payload1 or payload2, so that I can pass start() to write() and have the header and contiguous payload transmitted out the network? For example, if (sizeof(hdr) % BIG_STANDARD_ALIGNMENT) == 0) then derived classes of hdr will start without any extra padding?
An alternative is to use scatter/gather I/O, but that seems like a complicated setup, and I'm not sure it works to gather packet-fragments together for transmission in a single UDP packet.

How to define a well made message class in C++

At the moment I am working on a message class in C++ for data communication, e.g. over a serial port. For this question let's say I have two different messages (I do have more), e.g. a gyroscope- and a acceleration message both with calibration data and sensor values. Since I am an engineer who learned C++ for himself I had a look at my favorite C++ book and figured out that it might be useful to use a factory pattern for the message.
So a simplified version of my header file looks like this:
#ifndef MESSAGE_H
#define MESSAGE_H
#include <cstddef>
class message
{
public:
/**
* \brief ~message:
* Virtual destructor of the class message.
*/
virtual ~message();
/**
* \brief getMessage:
* Creates a message (with new).
*
* \param[in] size Size of the dataArray.
* \param[in] data Bytearray of the message.
*
* \return If messagetype in the Array data eqal to 0 => new GyroMessage.
* If messagetype in the Array data eqal to 1 => new AccelMessage.
* Else => new NotValidMessage.
*
*/
static message* getMessage(size_t size, char* data);
protected:
/**
* \brief message:
* Default konstructor of the class message.
*
* \param[in] size Size of the dataArray.
* \param[in] data Bytearray of the message.
*
*/
message(size_t size, char* data);
/// Size of the dataArray.
int size;
/// Bytearray of the message.
char* dataArray;
/// Type of message.
char messagetype;
};
#endif // MESSAGE_H
The clases GyroMessage, AccelMessage and NotValidMessage are child classes of message. There are two things I do not like about this pattern:
First: If I want to add a new message, it is now enough to add a new class which is inherited form message, you have to add another if statement is in the static function getMessage.
Second: If I want to use the data e.g. from the GyroMessage, I have to reinterpret_cast the message.
Is there a better pattern that I could use for this purpose?
I'm not sure my ideas are good but it costs nothing sharing.
I've done something similar few days ago for Arduino, and for my case I made this choices:
for me the data payload is a pod (plain old data) struct where the compiler is informed to pack it. To achieve so I used a define that handles the compiler directive to pack it (for g++ is __attribute__((packed)))
the class in my case handles almost everything, thus I written it with a template. The template is for the payload struct
for sending the message in byte array I used a templated union inside the class. You have to check the byte ordering of the sender and receiver if you use this method. Something like that:
template <class P>
union Packet {
P data;
unsigned char buff[sizeof(P)];
}
My toolchain supports template so I used them. But you can use more template to insert more packages inside the same union. You need only to remember to have a common field in all the struct that identifies the kind of package (see below).
my class does not handles reading and writing, but instead requires the user of the class to provide 2 callbacks for reading and writing that accepts as arguments the buffer itself, the dimension of the buffer and a void pointer for user data. I think this is a good way to make the class agnostic with respect to the transmission channel.
The example (I'm simplifying a lot):
template <class A, class B, std::size_t N>
union Packet {
A a;
B b;
unsigned char buffer[N];
};
#define PAYLOAD(X, Y) struct X \
Y __attribute__((packed)); \
typedef struct X X;
template <class A, class B, std::size_t N>
class Message {
union Packet<A, B, N> packet;
// [...]
}
// [...]
// Time to declare you messages
PAYLOAD(GyroMessage, { char type; float x; float y; })
PAYLOAD(AccelMessage, { char type; float x; float y; float z; })
// GyroMessage will always have type = 0x01 and
// AccelMessage will always have type = 0x02 for example
// you know that sizeof(AccelMessage) > sizeof(GyroMessage)
// there is for sure a way to automatize this thing at
// compilation time through macros.
// Time to declare the class
Message<GyroMessage, AccelMessage, sizeof(AccelMessage)> message;
To retrieve the correct value you can still (through the union) access the value that you want, without adding new particular functions. But at the moment I don't have a very nice way to access them programmatically.
Those are only some hints, I really don't know what you are doing or which are your priority. So take them with caution.
A factory function is an excellent solution when you want to work generically, with knowledge of which type to create either inferred or known only at the point of creation.
If you know what type you want to create, and you are planning to use the created class with a pointer to the specific, derived type (using its specific interface) then you do not need a factory function. Create what you need and use it! In that case, you need a base class only for common functionality and/or for passing to specific functions which work on all derived types generically.
Alternatively, if you do want to work generically, then you can use a factory function and not cast the result. Work with a pointer to the base class. Have a common interface and handle the differences internally. If you can not do this, then your scenario is not a candidate for this approach.

Packet wrangling from C to C++ or... how Neither Variant nor Any is a Union

The problem in a nutshell: I'm considering a rewrite of some packet handling code for a UDP protocol ... from C to C++. Obviously, I can just use the structures that I had with C to model the data, but then what would be the point? So, for the sake of argument, we have:
struct { uint8:2 type; uint8:6 con_id; uint16 seq_num } packet_header;
struct { packet_header ph; uint16 command; } control_packet;
struct { packet_header ph; uchar8 data[DATASIZE]; } data_packet;
In this case, "type" is 0 for data, 1 for control, 2 for encrypted data and 3 for encrypted control. There would also be structs reprenting each of the control packets, for argument, lets say "open" and "close".
Now... I would normally have a type that the function that fetches the packet returns and the function that sends accepts:
struct {
size_t pkt_len;
union {
uchar8 raw_packet[DATASIZE];
packet_header ph;
control_packet cp;
control_open_packet cop;
control_close_packet ccp;
data_packet dp;
} p;
} packet;
... this is all simplified for argument... but the point is: when sending a packet, we want to create a packet of a certain type and send a generic packet. Conversely, when receiving a packet, you want to receive a generic packet and and cast it to more specific types as you classify it.
So where's the question? My question is: if Variant and Any are not appropriate ways to express this, what are? Am I stuck with union in this case? Certainly I don't violate the stipulation of POD types (so far) for the union. I've been scouring both C++11 and Boost (and to some extent looking at C++14 ... although I'm stuck with C++11) and I don't see offered solutions.
You can use both union as it is in your example or class hierarchy with packet_header a the top and specific derived classes for each type of the packet:
struct packet_header { uint8:2 type; uint8:6 con_id; uint16 seq_num };
struct control_packet : packet_header { uint16 command; };
struct data_packet: packet_header { uchar8 data[DATASIZE]; };
struct packet
{
size_t pkt_len;
union
{
uchar8 raw_packet[DATASIZE];
packet_header ph;
control_packet cp;
control_open_packet cop;
control_close_packet ccp;
data_packet dp;
};
};
Maybe you need to seek for elegance and flexibility in the code that handles your packets. I doubt that defining data in some other way (using boost or using C++17 features) will lead to a considerable gain.
Note the anonymous union in the struct packet. It allows accessing fields of specific packet types directly. C++ style expects the name of the struct directly after the struct keyword.

JSON or protocol buffer to replace the custom TCP message

Originally, We have two applications communication with TCP/IP, and both of them are implemented by C++. The messages between them are custom message type.
Now the client program will be changed to web application based on nodejs and the communication between them will be changed to message bus such as rabbitmq
So the message type between them should be changed.
JSON comes to my mind first, however the custom messages are too complicated, which are defined by template and inheritance. It seems that convert the custom message to JSON is not a good option. Am I right?
class Address {
int network;
int addressType;
//...
};
class MsgType{
unsigned char msgSeq;
unsigned int msgLen;
//...
};
class Message{
Address destination;
Address source;
MsgType msgType;
//...
};
template <typename T, int RESPONSE_TYPE>
class ResponseMessage : public Message{
//...
}
typedef struct{
int number;
int type;
}ConfigResp;
class CfgResp : public ResponseMessage<ConfigResp, CONFIG_REQUEST>
{
//...
}
Protocol Buffers is another option for me to do that. What should I do?
redefine the custom message into protocol buffer? no no
Here is my solution: Just wrap the whole original custom message (binary type) into protocol buffer as one message in the server side, then decode the custom message(binary type) in client side. Is that possible?
It looks like you are structuring your application to become more extensible. Not using a nice message format is completely counter to that aim.
Don't embed your binary format inside a protocol buffer chunk. You'll gain nothing - you'll need to rewrite parsing and writing code for each component that wants to use the message bus. Thats wasted time and effort.
There is pain in mapping your C++ structures to JSON or protocol buffers. But it will make hooking into those messages using node.js or other things peeking into the message bus much easier later.
Personally I'd use protocol buffers - since they're more type safe. And there are differences between handling of various types in JSON libraries, because the JSON format is (intentionally) lax. In particular I've found handling of long integers problematic.
Typically I write a helper template struct for each class I need to convert - then conversion becomes a lot of boilerplate. Something like
template<typename T> class ProtocolBufferHelper {
}
template<> class ProtocolBufferHelper<Address> {
typedef address_buffer protocol_buffer_type;
void writeToProtocolBuffer( const Address &a, address_buffer & buffer) {
buffer.setNetwork(a.network);
...
}
...
}
template<> class ProtocolBufferHelper<Message> {
void writeToProtocolBuffer( const Message &m, address_buffer & buffer) {
::writeToProtocolBuffer(buffer.getDestination(), m.destination);
::writeToProtocolBuffer(buffer.getSource(), m.source);
...
}
}
template<typename T> void writeToProtocolBuffer( const T &value, ProtocolBufferHelper<T>::protocol_buffer_type & buffer ) {
ProtocolBufferHelper<T>::writeToProtocolBuffer(value, buffer);
}
You'll have to forgive me for not remembering exactly what the protocol buffer syntax is in C++ (its been a while...). but hopefully its enough to get you started.

class design on network packet parsing

I am looking for suggestions or design patterns to handle the parsing and generation of network packets (network or not by itself is not important per se). Each packet has a fixed length header and a variable length payload. The payload parsing will depend on the packet type. The straightforward way of doing this would be (assuming the input will come from a stream, console or network):
class Header {
public:
Header(istream &);
istream& read(istream &);
private:
uint32_t type;
uint32_t payload_length;
}
class PayloadTypeA {
public:
PayloadTypeA {}
istream& read(istream &);
private:
uint32_t payload_1;
uint32_t payload_2;
}
class PayloadTypeB {
...
}
The way I envision for the processing logic would be: read header first, then check the packet type, then decide which payload type to use to read the rest.
However, I feel this solution seems somewhat clumsy - I wonder if there is a better solution or design idioms I should follow?
thanks
Oliver
Usually, your header is something like this:
Contents in brackets [ ] is header data
[Header length, Data Type,] Data
If you want, you can have a dynamic header (of variable length):
[Header Length, Number of Chunks, Size of chunk 1, Size of chunk 2, Size of chunk 3 etc, Data Type,] Data
You can create your own custom header to match whatever you're sending.