The packet library handles network packets of a large number of protocols. We work with a packet on three levels
Whenever we are using a Packet, we are talking about a senf::Packet (or a senf::ConcretePacket). This class is a \e handle referencing an internally managed packet data structure. So even though we pass senf::Packet instances around by value, they work like references. The packet library automatically manages all required memory resources using reference counting. Different Packet handles may really internally share one Packet data structure if they both point to the same packet.
From the outside, a packet is just a bunch of bytes just as it is read from (or will be written to) the wire. At this low-level view, we can access the data in it's raw form but have no further information about what kind of packet we have. The packet library provides a consistent container interface for this representation.
This type of access is primarily needed when reading or writing packets (e.g. to/from the network). \see senf::Packet::data() \n senf::PacketData
On the next level, the packet is divided into a nested list of sub-packets (or headers) called interpreters. Each senf::Packet handle internally points to an interpreter or header. This allows us to access one and the same packet in different ways. Consider an Ethernet Packet with an IP payload holding a UDP packet. We may reference either the Ethernet packet as a whole or we may reference the IP or UDP interpreters (sub-packets or headers). All handles really refer to the \e same data structure but provide access to a different (sub-)range of the data in the packet. We can navigate around this chained structure using appropriate members:
\see \ref packet_module
On the next level, the packet library allows us to parse the individual protocols. This gives us access to the protocol specific data members of a packet and allows us to access or manipulate a packet in a protocol specific way. To access this information, we need to use a protocol specific handle, the senf::ConcretePacket which takes as a template argument the specific type of packet to be interpreted. This allows us to easily interpret or create packets. Here an example on how to create a new Ethernet / IP / UDP / Payload packet interpreter chain:
Again, realize, that \a eth, \a ip, \a udp and \a payload share the same internal packet data structure (the respective \c data() members all provide access to the same underlying container however at different byte ranges): The complete packet can be accessed at <tt>eth.data()</tt> whereas <tt>payload.data()</tt> only holds UDP payload (in this case the string "Hello, world!"). \see \ref packetparser \n \ref protocolbundles