I work on embedded systems, so frequently, I am required to implement protocols. When I do this I like to make nice clean layers.
However, this become difficult where the fields used by different layers are shared.
I like to think of the layers as offering a number of services following the spirit of OSI model:
1. start byte / sequence (SOF)
2. length of packet / message
3. message integrity (CRC, xor checksum)
4. Source / Destination
5. Command / Response Type (how to interpret payload).
(I realize this is not the ISO model, but you get the point I hope.)
Sometimes the protocol exists on a point to point link (RS232 or tcp socket) so there is no concept of source and destination.
I would typically have a software layer for each of: Framing, Network and Application. The layer is typically a state machine processing bytes, or frames or packets. At the top, there is a hook point for the application specific functionality.
Typically as a packet moves up the stack and the layers are stripped off, I simply pass a pointer to the next inner scope. First pointer to SOF, then pointer to network fields and finally a pointer to the application payload.
As the fields are parsed they are added to a structure specific to the layer producing it. (A structure with a name like: Frame, Packet, Message / Command / Response) Each structure has a pointer to the packet buffer.
At the top I can deallocate the structure by calling free on each layer until at the bottom a pointer is available to free. (or return to a pool)
The question is how can I cleanly handle cases where the fields have dual use or are bit fields in a byte. (upper nibble is payload length, lower nibble is packet type, etc...)
An example of this is a simple packet format like this:
<SOF> <CMD> <command specific payload> <CRC>
In this case the length of the packet is implied by the command code. So the CMD field (a single byte in this case) is shared between the framing and application layers.
I think in this case the framing layer has a lookup table for command to length and passes a pointer to the CMD field up to the application layer for handling in a structure.