class design on network packet parsing - c++

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.

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.

Design pattern for message packet header

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.

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.

Finding a good modelisation for some objects

For a school project, I need to send and receive some data named as TLV through the network.
In fact, because a TLV can be small, the application send a meta-TLV that groups several TLV in a packet.
My problem is the following : what are the classes that I need to create to modelise properly the TLV ?
I don't know if I need to mention all the TLV possible but what I know is the following :
-Every TLV has a field type that identify the semantic of the TLV
-Every TLV but one has a field length. However for five TLV, this sized is fixed
-Two TLV has exactly the same field : type, length=0
-Three TLV has exactly the same field : type, length=8 and id. Just the type change (and their name)
The other are quite different.
My first idea was to use a mother class TLV that has a enum to store all the different TLV allowed like this :
//enum class to avoid conflicts
enum class TlvType {
Pad1,
PadN,
Bad,
No,
PeersReq,
Peers,
Data,
IHave,
IDontHave,
INeed,
// Unknown,
};
class Tlv {
private:
virtual void to_stream(std::ostream& output) const = 0;
protected:
uint8_t length_;
public:
virtual TlvType type() const = 0;
/*Solution find here : http://stackoverflow.com/questions/2059058/c-abstract-class-operator-overloading-and-interface-enforcement-question*/
friend std::ostream &operator<<(std::ostream& output, const Tlv& tlv) {
tlv.to_stream(output);
return output;
}
//TO DO : do we really need that this method is virtual ?
virtual uint8_t length() const;
Tlv();
virtual ~Tlv() {}
};
class PadN : public Tlv {
private:
void to_stream(std::ostream& output) const;
static constexpr TlvType code() {return TlvType::PadN;}
public:
TlvType type() const;
PadN();
PadN(uint8_t zero_bytes);
void set_length(uint8_t length);
};
The problem is that this codes somehow an algebraic type, that introduces a lot of redundant code. For example, I need to define for each tlv the method TlvType type() const . Since some Tlv has a fixed size, I only want a setter for the ones that can change their size.
Moreover each Tlv will be then formated in a format ready to send to the network. This, looks like a lot to serialization. However, I think that serialization is overkill for this project. Besides, since it's a network project, each student use his own language. And the only thing that we know is the format of a tlv that needs to be sent through the network.
Because my code is quite redundant I think that my modelisation is wrong for the TLV. And I'm doubting about using a class for each TLV. Indeed, probably the user won't change his TLV once he created it. He just wants to send it. And there is the same problem for the other way: I need to receive TLV. So I'm not sure how should I do.

How Protocol buffer interact with legacy protocol code

every one, I have a question about how protocol buffer interact with existed protocol mechanism,Say code below:
class PacketBase
{
public:
PacketBase();
private:
int msgType;
int msgLen;
private:
MessageBuilder* m_pMsgBuilder; /// do Write and Read From msg stream
};
class LoginRequest : public PacketBase
{
/// here we can use proto replace the msg field defined here
/// invoke write or read method in packetbase to serialze or de-serialize
};
Can protocol buffer do the job while maintain the class hierarchy unchanged?
Well, since your msgType and msgLen fields are both private, I think your question boils down to "Can I replace LoginRequest with a protocol buffer that has a no-args constructor?" and the answer here is an unqualified "yes".
Protocol buffers take care of (de-)serializing fields while maintaining type information; there's really no reason for you to write that code yourself. If you were to create a LoginRequest protobuf, for example, you could just construct it, call setters to set its fields, and then serialize it to an ostringstream. That's probably sufficient for what you want, right?