# HG changeset patch # User Tom Henderson # Date 1496154324 25200 # Tue May 30 07:25:24 2017 -0700 # Node ID 1dd3e78828daf63596b6c0276907dc2316c01c17 # Parent 34493978d2ae136daa59cc0f10eb33c2e210e68e enable deserialization of variable-sized headers and trailers diff -r 34493978d2ae -r 1dd3e78828da src/network/model/chunk.cc --- a/src/network/model/chunk.cc Sun May 28 22:22:41 2017 +0200 +++ b/src/network/model/chunk.cc Tue May 30 07:25:24 2017 -0700 @@ -34,4 +34,12 @@ return tid; } +// This default implementation is provided for backward compatibility +// reasons. Subclasses should implement this method themselves. +uint32_t +Chunk::Deserialize (Buffer::Iterator start, Buffer::Iterator end) +{ + return Deserialize (start); +} + } // namespace ns3 diff -r 34493978d2ae -r 1dd3e78828da src/network/model/chunk.h --- a/src/network/model/chunk.h Sun May 28 22:22:41 2017 +0200 +++ b/src/network/model/chunk.h Tue May 30 07:25:24 2017 -0700 @@ -42,12 +42,32 @@ /** * \brief Deserialize the object from a buffer iterator + * + * This version of Deserialize can be used when the Chunk has a fixed + * size. It should not be called for variable-sized Chunk derived types + * (but must be implemented, for historical reasons). + * * \param start the buffer iterator * \returns the number of deserialized bytes */ virtual uint32_t Deserialize (Buffer::Iterator start) = 0; /** + * \brief Deserialize the object from a buffer iterator + * + * This version of Deserialize must be used when the Chunk has a variable + * size, because the bounds of the Chunk may not be known at the point + * of deserialization (e.g. a sequence of TLV fields). + * + * The size of the chunk should be start.GetDistanceFrom (end); + * + * \param start the starting point + * \param end the ending point + * \returns the number of deserialized bytes + */ + virtual uint32_t Deserialize (Buffer::Iterator start, Buffer::Iterator end); + + /** * \brief Print the object contents * \param os the output stream */ diff -r 34493978d2ae -r 1dd3e78828da src/network/model/header.h --- a/src/network/model/header.h Sun May 28 22:22:41 2017 +0200 +++ b/src/network/model/header.h Tue May 30 07:25:24 2017 -0700 @@ -48,6 +48,8 @@ */ static TypeId GetTypeId (void); virtual ~Header (); + + using Chunk::Deserialize; /** * \returns the expected size of the header. * diff -r 34493978d2ae -r 1dd3e78828da src/network/model/packet.cc --- a/src/network/model/packet.cc Sun May 28 22:22:41 2017 +0200 +++ b/src/network/model/packet.cc Tue May 30 07:25:24 2017 -0700 @@ -264,6 +264,19 @@ m_metadata.AddHeader (header, size); } uint32_t +Packet::RemoveHeader (Header &header, uint32_t size) +{ + Buffer::Iterator end; + end = m_buffer.Begin (); + end.Next (size); + uint32_t deserialized = header.Deserialize (m_buffer.Begin (), end); + NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized); + m_buffer.RemoveAtStart (deserialized); + m_byteTagList.Adjust (-deserialized); + m_metadata.RemoveHeader (header, deserialized); + return deserialized; +} +uint32_t Packet::RemoveHeader (Header &header) { uint32_t deserialized = header.Deserialize (m_buffer.Begin ()); @@ -280,6 +293,16 @@ NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized); return deserialized; } +uint32_t +Packet::PeekHeader (Header &header, uint32_t size) const +{ + Buffer::Iterator end; + end = m_buffer.Begin (); + end.Next (size); + uint32_t deserialized = header.Deserialize (m_buffer.Begin (), end); + NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized); + return deserialized; +} void Packet::AddTrailer (const Trailer &trailer) { @@ -445,7 +468,22 @@ NS_ASSERT (instance != 0); Chunk *chunk = dynamic_cast (instance); NS_ASSERT (chunk != 0); - chunk->Deserialize (item.current); + if (item.type == PacketMetadata::Item::HEADER) + { + Buffer::Iterator end = item.current; + end.Next (item.currentSize); // move from start + chunk->Deserialize (item.current, end); + } + else if (item.type == PacketMetadata::Item::TRAILER) + { + Buffer::Iterator start = item.current; + start.Prev (item.currentSize); // move from end + chunk->Deserialize (start, item.current); + } + else + { + chunk->Deserialize (item.current); + } chunk->Print (os); delete chunk; } diff -r 34493978d2ae -r 1dd3e78828da src/network/model/packet.h --- a/src/network/model/packet.h Sun May 28 22:22:41 2017 +0200 +++ b/src/network/model/packet.h Tue May 30 07:25:24 2017 -0700 @@ -316,13 +316,26 @@ /** * \brief Deserialize and remove the header from the internal buffer. * - * This method invokes Header::Deserialize. + * This method invokes Header::Deserialize (begin) and should be used for + * variable-length headers. * * \param header a reference to the header to remove from the internal buffer. * \returns the number of bytes removed from the packet. */ uint32_t RemoveHeader (Header &header); /** + * \brief Deserialize and remove the header from the internal buffer. + * + * This method invokes Header::Deserialize (begin, end) and should be + * used for variable-length headers (where the size is determined somehow + * by the caller). + * + * \param header a reference to the header to remove from the internal buffer. + * \param size number of bytes to deserialize + * \returns the number of bytes removed from the packet. + */ + uint32_t RemoveHeader (Header &header, uint32_t size); + /** * \brief Deserialize but does _not_ remove the header from the internal buffer. * s * This method invokes Header::Deserialize. @@ -332,6 +345,18 @@ */ uint32_t PeekHeader (Header &header) const; /** + * \brief Deserialize but does _not_ remove the header from the internal buffer. + * s + * This method invokes Header::Deserialize (begin, end) and should be used + * for variable-length headers (where the size is determined somehow + * by the caller). + * + * \param header a reference to the header to read from the internal buffer. + * \param size number of bytes to deserialize + * \returns the number of bytes read from the packet. + */ + uint32_t PeekHeader (Header &header, uint32_t size) const; + /** * \brief Add trailer to this packet. * * This method invokes the diff -r 34493978d2ae -r 1dd3e78828da src/network/model/trailer.cc --- a/src/network/model/trailer.cc Sun May 28 22:22:41 2017 +0200 +++ b/src/network/model/trailer.cc Tue May 30 07:25:24 2017 -0700 @@ -42,6 +42,14 @@ return tid; } +// This default implementation is provided for backward compatibility +// reasons. Subclasses should implement this method themselves. +uint32_t +Trailer::Deserialize (Buffer::Iterator start, Buffer::Iterator end) +{ + return Deserialize (end); +} + std::ostream & operator << (std::ostream &os, const Trailer &trailer) { trailer.Print (os); diff -r 34493978d2ae -r 1dd3e78828da src/network/model/trailer.h --- a/src/network/model/trailer.h Sun May 28 22:22:41 2017 +0200 +++ b/src/network/model/trailer.h Tue May 30 07:25:24 2017 -0700 @@ -79,10 +79,28 @@ * representation of this trailer in real networks. * The input iterator points to the end of the area where the * data shall be written. This method is thus expected to call - * Buffer::Iterator::Prev prio to actually reading any data. + * Buffer::Iterator::Prev prior to actually reading any data. */ virtual uint32_t Deserialize (Buffer::Iterator end) = 0; /** + * \param start an iterator which points to the start of the buffer + * where the trailer should be read from. + * \param end an iterator which points to the end of the buffer + * where the trailer should be read from. + * \returns the number of bytes read. + * + * This method is used by Packet::RemoveTrailer to + * re-create a trailer from the byte buffer of a packet. + * The data read is expected to match bit-for-bit the + * representation of this trailer in real networks. + * The input iterator end points to the end of the area where the + * data shall be written. + * + * This variant should be provided by any variable-sized trailer subclass + * (i.e. if GetSerializedSize () does not return a constant). + */ + virtual uint32_t Deserialize (Buffer::Iterator start, Buffer::Iterator end); + /** * \param os output stream * This method is used by Packet::Print to print the * content of a trailer as ascii data to a c++ output stream.