In C, when you want to parse for instance an Ethernet frame, you declare a struct like that:
struct ether_header {
u_char dst_addr[6];
u_char src_addr[6];
u_short ether_type;
};
Then, when you have the frame data, you cast it like that:
(struct ether_header*)(frame_data)
And access the fields respectively.
This does the job for procedural programming nicely, but it is in fact a bad solution when it comes to object-oriented programming, because you have different structs for different PDUs: IPv4 packet, IPv6 packet and so on. This implies loads of if-statements which leads to poor maintenance. What is worse, when you receive an Ethernet frame and want to continue parsing up the protocol stack, you'll check the ether_type and then instantiate the IPv4 packet parser, IPv6 parser or whatever is the value of the EtherType. Later on, if you parsed an IPv4 packet, you look into its Protocol field to determine whether the upper-layer protocol is TCP, UDP or something else and again instantiate a different parser. This is an obvious code smell.
Therefore, I'm looking for a common idiom or a design pattern for doing that kind of parsing which would allow me to easily implement parsers for different protocols on each layer of the TCP/IP stack without having to deal with wild if-statements or redundancy.
What I currently have thought about is plenty of designs, but all of them involve breaking SOLID principles and were generally bad design decisions. I also tried adapting the classical Chain of Responsibility GoF pattern, but it really doesn't fit here because the requesting object in fact does know which object has to handle the request.
Aucun commentaire:
Enregistrer un commentaire