src/common/packet.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Thu Nov 12 13:01:01 2009 +0100 (2009-11-12)
changeset 5505 c0ac392289c3
parent 5334 92aafeab5e4f
child 5938 69bcae35bc81
permissions -rw-r--r--
replace RefCountBase with SimpleRefCount<> to avoid duplicate refcounting implementations.
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     3  * Copyright (c) 2005,2006 INRIA
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License version 2 as
     7  * published by the Free Software Foundation;
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  *
    18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
    19  */
    20 #include "packet.h"
    21 #include "ns3/assert.h"
    22 #include "ns3/log.h"
    23 #include "ns3/test.h"
    24 #include <string>
    25 #include <stdarg.h>
    26 
    27 NS_LOG_COMPONENT_DEFINE ("Packet");
    28 
    29 namespace ns3 {
    30 
    31 uint32_t Packet::m_globalUid = 0;
    32 
    33 TypeId 
    34 ByteTagIterator::Item::GetTypeId (void) const
    35 {
    36   return m_tid;
    37 }
    38 uint32_t 
    39 ByteTagIterator::Item::GetStart (void) const
    40 {
    41   return m_start;
    42 }
    43 uint32_t 
    44 ByteTagIterator::Item::GetEnd (void) const
    45 {
    46   return m_end;
    47 }
    48 void 
    49 ByteTagIterator::Item::GetTag (Tag &tag) const
    50 {
    51   if (tag.GetInstanceTypeId () != GetTypeId ())
    52     {
    53       NS_FATAL_ERROR ("The tag you provided is not of the right type.");
    54     }
    55   tag.Deserialize (m_buffer);
    56 }
    57 ByteTagIterator::Item::Item (TypeId tid, uint32_t start, uint32_t end, TagBuffer buffer)
    58   : m_tid (tid),
    59     m_start (start),
    60     m_end (end),
    61     m_buffer (buffer)
    62 {}
    63 bool 
    64 ByteTagIterator::HasNext (void) const
    65 {
    66   return m_current.HasNext ();
    67 }
    68 ByteTagIterator::Item 
    69 ByteTagIterator::Next (void)
    70 {
    71   ByteTagList::Iterator::Item i = m_current.Next ();
    72   return ByteTagIterator::Item (i.tid, 
    73                                 i.start-m_current.GetOffsetStart (), 
    74                                 i.end-m_current.GetOffsetStart (), 
    75                                 i.buf);
    76 }
    77 ByteTagIterator::ByteTagIterator (ByteTagList::Iterator i)
    78   : m_current (i)
    79 {}
    80 
    81 
    82 PacketTagIterator::PacketTagIterator (const struct PacketTagList::TagData *head)
    83   : m_current (head)
    84 {}
    85 bool 
    86 PacketTagIterator::HasNext (void) const
    87 {
    88   return m_current != 0;
    89 }
    90 PacketTagIterator::Item 
    91 PacketTagIterator::Next (void)
    92 {
    93   NS_ASSERT (HasNext ());
    94   const struct PacketTagList::TagData *prev = m_current;
    95   m_current = m_current->next;
    96   return PacketTagIterator::Item (prev);
    97 }
    98 
    99 PacketTagIterator::Item::Item (const struct PacketTagList::TagData *data)
   100   : m_data (data)
   101 {}
   102 TypeId 
   103 PacketTagIterator::Item::GetTypeId (void) const
   104 {
   105   return m_data->tid;
   106 }
   107 void 
   108 PacketTagIterator::Item::GetTag (Tag &tag) const
   109 {
   110   NS_ASSERT (tag.GetInstanceTypeId () == m_data->tid);
   111   tag.Deserialize (TagBuffer ((uint8_t*)m_data->data, (uint8_t*)m_data->data+PACKET_TAG_MAX_SIZE));
   112 }
   113 
   114 
   115 Ptr<Packet> 
   116 Packet::Copy (void) const
   117 {
   118   // we need to invoke the copy constructor directly
   119   // rather than calling Create because the copy constructor
   120   // is private.
   121   return Ptr<Packet> (new Packet (*this), false);
   122 }
   123 
   124 Packet::Packet ()
   125   : m_buffer (),
   126     m_byteTagList (),
   127     m_packetTagList (),
   128     m_metadata (m_globalUid, 0),
   129     m_nixVector (0)
   130 {
   131   m_globalUid++;
   132 }
   133 
   134 Packet::Packet (const Packet &o)
   135   : m_buffer (o.m_buffer),
   136     m_byteTagList (o.m_byteTagList),
   137     m_packetTagList (o.m_packetTagList),
   138     m_metadata (o.m_metadata)
   139 {
   140   o.m_nixVector ? m_nixVector = o.m_nixVector->Copy () 
   141                 : m_nixVector = 0;
   142 }
   143 
   144 Packet &
   145 Packet::operator = (const Packet &o)
   146 {
   147   if (this == &o)
   148     {
   149       return *this;
   150     }
   151   m_buffer = o.m_buffer;
   152   m_byteTagList = o.m_byteTagList;
   153   m_packetTagList = o.m_packetTagList;
   154   m_metadata = o.m_metadata;
   155   o.m_nixVector ? m_nixVector = o.m_nixVector->Copy () 
   156                 : m_nixVector = 0;
   157   return *this;
   158 }
   159 
   160 Packet::Packet (uint32_t size)
   161   : m_buffer (size),
   162     m_byteTagList (),
   163     m_packetTagList (),
   164     m_metadata (m_globalUid, size),
   165     m_nixVector (0)
   166 {
   167   m_globalUid++;
   168 }
   169 Packet::Packet (uint8_t const*buffer, uint32_t size)
   170   : m_buffer (),
   171     m_byteTagList (),
   172     m_packetTagList (),
   173     m_metadata (m_globalUid, size),
   174     m_nixVector (0)
   175 {
   176   m_globalUid++;
   177   m_buffer.AddAtStart (size);
   178   Buffer::Iterator i = m_buffer.Begin ();
   179   i.Write (buffer, size);
   180 }
   181 
   182 Packet::Packet (const Buffer &buffer,  const ByteTagList &byteTagList, 
   183                 const PacketTagList &packetTagList, const PacketMetadata &metadata)
   184   : m_buffer (buffer),
   185     m_byteTagList (byteTagList),
   186     m_packetTagList (packetTagList),
   187     m_metadata (metadata),
   188     m_nixVector (0)
   189 {}
   190 
   191 Ptr<Packet>
   192 Packet::CreateFragment (uint32_t start, uint32_t length) const
   193 {
   194   NS_LOG_FUNCTION (this << start << length);
   195   Buffer buffer = m_buffer.CreateFragment (start, length);
   196   NS_ASSERT (m_buffer.GetSize () >= start + length);
   197   uint32_t end = m_buffer.GetSize () - (start + length);
   198   PacketMetadata metadata = m_metadata.CreateFragment (start, end);
   199   // again, call the constructor directly rather than
   200   // through Create because it is private.
   201   return Ptr<Packet> (new Packet (buffer, m_byteTagList, m_packetTagList, metadata), false);
   202 }
   203 
   204 void
   205 Packet::SetNixVector (Ptr<NixVector> nixVector)
   206 {
   207   m_nixVector = nixVector;
   208 }
   209 
   210 Ptr<NixVector>
   211 Packet::GetNixVector (void) const
   212 {
   213   return m_nixVector;
   214 } 
   215 
   216 uint32_t 
   217 Packet::GetSize (void) const
   218 {
   219   return m_buffer.GetSize ();
   220 }
   221 
   222 void
   223 Packet::AddHeader (const Header &header)
   224 {
   225   uint32_t size = header.GetSerializedSize ();
   226   NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << size);
   227   uint32_t orgStart = m_buffer.GetCurrentStartOffset ();
   228   bool resized = m_buffer.AddAtStart (size);
   229   if (resized)
   230     {
   231       m_byteTagList.AddAtStart (m_buffer.GetCurrentStartOffset () + size - orgStart,
   232                                 m_buffer.GetCurrentStartOffset () + size);
   233     }
   234   header.Serialize (m_buffer.Begin ());
   235   m_metadata.AddHeader (header, size);
   236 }
   237 uint32_t
   238 Packet::RemoveHeader (Header &header)
   239 {
   240   uint32_t deserialized = header.Deserialize (m_buffer.Begin ());
   241   NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized);
   242   m_buffer.RemoveAtStart (deserialized);
   243   m_metadata.RemoveHeader (header, deserialized);
   244   return deserialized;
   245 }
   246 uint32_t
   247 Packet::PeekHeader (Header &header) const
   248 {
   249   uint32_t deserialized = header.Deserialize (m_buffer.Begin ());
   250   NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized);
   251   return deserialized;
   252 }
   253 void
   254 Packet::AddTrailer (const Trailer &trailer)
   255 {
   256   uint32_t size = trailer.GetSerializedSize ();
   257   NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << size);
   258   uint32_t orgStart = m_buffer.GetCurrentStartOffset ();
   259   bool resized = m_buffer.AddAtEnd (size);
   260   if (resized)
   261     {
   262       m_byteTagList.AddAtEnd (m_buffer.GetCurrentStartOffset () - orgStart,
   263                               m_buffer.GetCurrentEndOffset () - size);
   264     }
   265   Buffer::Iterator end = m_buffer.End ();
   266   trailer.Serialize (end);
   267   m_metadata.AddTrailer (trailer, size);
   268 }
   269 uint32_t
   270 Packet::RemoveTrailer (Trailer &trailer)
   271 {
   272   uint32_t deserialized = trailer.Deserialize (m_buffer.End ());
   273   NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << deserialized);
   274   m_buffer.RemoveAtEnd (deserialized);
   275   m_metadata.RemoveTrailer (trailer, deserialized);
   276   return deserialized;
   277 }
   278 uint32_t
   279 Packet::PeekTrailer (Trailer &trailer)
   280 {
   281   uint32_t deserialized = trailer.Deserialize (m_buffer.End ());
   282   NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << deserialized);
   283   return deserialized;
   284 }
   285 
   286 void 
   287 Packet::AddAtEnd (Ptr<const Packet> packet)
   288 {
   289   NS_LOG_FUNCTION (this << packet << packet->GetSize ());
   290   uint32_t aStart = m_buffer.GetCurrentStartOffset ();
   291   uint32_t bEnd = packet->m_buffer.GetCurrentEndOffset ();
   292   m_buffer.AddAtEnd (packet->m_buffer);
   293   uint32_t appendPrependOffset = m_buffer.GetCurrentEndOffset () - packet->m_buffer.GetSize ();
   294   m_byteTagList.AddAtEnd (m_buffer.GetCurrentStartOffset () - aStart, 
   295                           appendPrependOffset);
   296   ByteTagList copy = packet->m_byteTagList;
   297   copy.AddAtStart (m_buffer.GetCurrentEndOffset () - bEnd,
   298                    appendPrependOffset);
   299   m_byteTagList.Add (copy);
   300   m_metadata.AddAtEnd (packet->m_metadata);
   301 }
   302 void
   303 Packet::AddPaddingAtEnd (uint32_t size)
   304 {
   305   NS_LOG_FUNCTION (this << size);
   306   uint32_t orgEnd = m_buffer.GetCurrentEndOffset ();
   307   bool resized = m_buffer.AddAtEnd (size);
   308   if (resized)
   309     {
   310       m_byteTagList.AddAtEnd (m_buffer.GetCurrentEndOffset () - orgEnd,
   311                               m_buffer.GetCurrentEndOffset () - size);
   312     }
   313   m_metadata.AddPaddingAtEnd (size);
   314 }
   315 void 
   316 Packet::RemoveAtEnd (uint32_t size)
   317 {
   318   NS_LOG_FUNCTION (this << size);
   319   m_buffer.RemoveAtEnd (size);
   320   m_metadata.RemoveAtEnd (size);
   321 }
   322 void 
   323 Packet::RemoveAtStart (uint32_t size)
   324 {
   325   NS_LOG_FUNCTION (this << size);
   326   m_buffer.RemoveAtStart (size);
   327   m_metadata.RemoveAtStart (size);
   328 }
   329 
   330 void 
   331 Packet::RemoveAllByteTags (void)
   332 {
   333   NS_LOG_FUNCTION (this);
   334   m_byteTagList.RemoveAll ();
   335 }
   336 
   337 uint8_t const *
   338 Packet::PeekData (void) const
   339 {
   340   NS_LOG_FUNCTION (this);
   341   uint32_t oldStart = m_buffer.GetCurrentStartOffset ();
   342   uint8_t const * data = m_buffer.PeekData ();
   343   uint32_t newStart = m_buffer.GetCurrentStartOffset ();
   344  
   345   // Update tag offsets if buffer offsets were changed
   346   const_cast<ByteTagList &>(m_byteTagList).AddAtStart (newStart - oldStart, newStart);
   347   return data;
   348 }
   349 
   350 uint32_t 
   351 Packet::CopyData (uint8_t *buffer, uint32_t size) const
   352 {
   353   Buffer::Iterator i = m_buffer.Begin ();
   354   uint32_t cur = 0;
   355   while (!i.IsEnd () && cur < size)
   356     {
   357       buffer[cur] = i.ReadU8 ();
   358       cur++;
   359     }
   360   return cur;
   361 }
   362 
   363 void
   364 Packet::CopyData(std::ostream *os, uint32_t size) const
   365 {
   366   return m_buffer.CopyData (os, size);
   367 }
   368 
   369 uint32_t 
   370 Packet::GetUid (void) const
   371 {
   372   return m_metadata.GetUid ();
   373 }
   374 
   375 void 
   376 Packet::PrintByteTags (std::ostream &os) const
   377 {
   378   ByteTagIterator i = GetByteTagIterator ();
   379   while (i.HasNext ())
   380     {
   381       ByteTagIterator::Item item = i.Next ();
   382       os << item.GetTypeId ().GetName () << " [" << item.GetStart () << "-" << item.GetEnd () << "]";
   383       Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
   384       if (constructor.IsNull ())
   385         {
   386           if (i.HasNext ())
   387             {
   388               os << " ";
   389             }
   390           continue;
   391         }
   392       Tag *tag = dynamic_cast<Tag *> (constructor ());
   393       NS_ASSERT (tag != 0);
   394       os << " ";
   395       item.GetTag (*tag);
   396       tag->Print (os);
   397       if (i.HasNext ())
   398         {
   399           os << " ";
   400         }
   401       delete tag;
   402     }
   403 }
   404 
   405 void 
   406 Packet::Print (std::ostream &os) const
   407 {
   408   PacketMetadata::ItemIterator i = m_metadata.BeginItem (m_buffer);
   409   while (i.HasNext ())
   410     {
   411       PacketMetadata::Item item = i.Next ();
   412       if (item.isFragment)
   413         {
   414           switch (item.type) {
   415           case PacketMetadata::Item::PAYLOAD:
   416             os << "Payload";
   417             break;
   418           case PacketMetadata::Item::HEADER:
   419           case PacketMetadata::Item::TRAILER:
   420             os << item.tid.GetName ();
   421             break;
   422           }
   423           os << " Fragment [" << item.currentTrimedFromStart<<":"
   424              << (item.currentTrimedFromStart + item.currentSize) << "]";
   425         }
   426       else
   427         {
   428           switch (item.type) {
   429           case PacketMetadata::Item::PAYLOAD:
   430             os << "Payload (size=" << item.currentSize << ")";
   431             break;
   432           case PacketMetadata::Item::HEADER:
   433           case PacketMetadata::Item::TRAILER:
   434             os << item.tid.GetName () << " (";
   435             {
   436               NS_ASSERT (item.tid.HasConstructor ());
   437               Callback<ObjectBase *> constructor = item.tid.GetConstructor ();
   438               NS_ASSERT (!constructor.IsNull ());
   439               ObjectBase *instance = constructor ();
   440               NS_ASSERT (instance != 0);
   441               Chunk *chunk = dynamic_cast<Chunk *> (instance);
   442               NS_ASSERT (chunk != 0);
   443               chunk->Deserialize (item.current);
   444               chunk->Print (os);
   445               delete chunk;
   446             }
   447             os << ")";
   448             break;
   449           }          
   450         }
   451       if (i.HasNext ())
   452         {
   453           os << " ";
   454         }
   455     }
   456 #if 0
   457   // The code below will work only if headers and trailers
   458   // define the right attributes which is not the case for
   459   // now. So, as a temporary measure, we use the 
   460   // headers' and trailers' Print method as shown above.
   461   PacketMetadata::ItemIterator i = m_metadata.BeginItem (m_buffer);
   462   while (i.HasNext ())
   463     {
   464       PacketMetadata::Item item = i.Next ();
   465       if (item.isFragment)
   466         {
   467           switch (item.type) {
   468           case PacketMetadata::Item::PAYLOAD:
   469             os << "Payload";
   470             break;
   471           case PacketMetadata::Item::HEADER:
   472           case PacketMetadata::Item::TRAILER:
   473             os << item.tid.GetName ();
   474             break;
   475           }
   476           os << " Fragment [" << item.currentTrimedFromStart<<":"
   477              << (item.currentTrimedFromStart + item.currentSize) << "]";
   478         }
   479       else
   480         {
   481           switch (item.type) {
   482           case PacketMetadata::Item::PAYLOAD:
   483             os << "Payload (size=" << item.currentSize << ")";
   484             break;
   485           case PacketMetadata::Item::HEADER:
   486           case PacketMetadata::Item::TRAILER:
   487             os << item.tid.GetName () << "(";
   488             {
   489               NS_ASSERT (item.tid.HasConstructor ());
   490               Callback<ObjectBase *> constructor = item.tid.GetConstructor ();
   491               NS_ASSERT (constructor.IsNull ());
   492               ObjectBase *instance = constructor ();
   493               NS_ASSERT (instance != 0);
   494               Chunk *chunk = dynamic_cast<Chunk *> (instance);
   495               NS_ASSERT (chunk != 0);
   496               chunk->Deserialize (item.current);
   497               for (uint32_t j = 0; j < item.tid.GetAttributeN (); j++)
   498                 {
   499                   std::string attrName = item.tid.GetAttributeName (j);
   500                   std::string value;
   501                   bool ok = chunk->GetAttribute (attrName, value);
   502                   NS_ASSERT (ok);
   503                   os << attrName << "=" << value;
   504                   if ((j + 1) < item.tid.GetAttributeN ())
   505                     {
   506                       os << ",";
   507                     }
   508                 }
   509             }
   510             os << ")";
   511             break;
   512           }          
   513         }
   514       if (i.HasNext ())
   515         {
   516           os << " ";
   517         }
   518     }
   519 #endif   
   520 }
   521 
   522 PacketMetadata::ItemIterator 
   523 Packet::BeginItem (void) const
   524 {
   525   return m_metadata.BeginItem (m_buffer);
   526 }
   527 
   528 void
   529 Packet::EnablePrinting (void)
   530 {
   531   NS_LOG_FUNCTION_NOARGS ();
   532   PacketMetadata::Enable ();
   533 }
   534 
   535 void
   536 Packet::EnableChecking (void)
   537 {
   538   NS_LOG_FUNCTION_NOARGS ();
   539   PacketMetadata::EnableChecking ();
   540 }
   541 
   542 Buffer 
   543 Packet::Serialize (void) const
   544 {
   545   NS_LOG_FUNCTION (this);
   546   Buffer buffer;
   547   uint32_t reserve;
   548 
   549   // write metadata
   550   reserve = m_metadata.GetSerializedSize ();
   551   buffer.AddAtStart (reserve);
   552   m_metadata.Serialize (buffer.Begin (), reserve);
   553 
   554   // write tags
   555   //XXX
   556   //reserve = m_tags.GetSerializedSize ();
   557   //buffer.AddAtStart (reserve);
   558   //m_tags.Serialize (buffer.Begin (), reserve);
   559   
   560   // aggregate byte buffer, metadata, and tags
   561   Buffer tmp = m_buffer.CreateFullCopy ();
   562   tmp.AddAtEnd (buffer);
   563   
   564   // write byte buffer size.
   565   tmp.AddAtStart (4);
   566   tmp.Begin ().WriteU32 (m_buffer.GetSize ());
   567 
   568   return tmp;
   569 }
   570 void 
   571 Packet::Deserialize (Buffer buffer)
   572 {
   573   NS_LOG_FUNCTION (this);
   574   Buffer buf = buffer;
   575   // read size
   576   uint32_t packetSize = buf.Begin ().ReadU32 ();
   577   buf.RemoveAtStart (4);
   578 
   579   // read buffer.
   580   buf.RemoveAtEnd (buf.GetSize () - packetSize);
   581   m_buffer = buf;
   582   buffer.RemoveAtStart (4 + packetSize);
   583 
   584 
   585   // read tags
   586   //XXX
   587   //uint32_t tagsDeserialized = m_tags.Deserialize (buffer.Begin ());
   588   //buffer.RemoveAtStart (tagsDeserialized);
   589 
   590   // read metadata
   591   uint32_t metadataDeserialized = 
   592     m_metadata.Deserialize (buffer.Begin ());
   593   buffer.RemoveAtStart (metadataDeserialized);
   594 }
   595 
   596 void 
   597 Packet::AddByteTag (const Tag &tag) const
   598 {
   599   NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
   600   ByteTagList *list = const_cast<ByteTagList *> (&m_byteTagList);
   601   TagBuffer buffer = list->Add (tag.GetInstanceTypeId (), tag.GetSerializedSize (), 
   602                                 m_buffer.GetCurrentStartOffset (),
   603                                 m_buffer.GetCurrentEndOffset ());
   604   tag.Serialize (buffer);
   605 }
   606 ByteTagIterator 
   607 Packet::GetByteTagIterator (void) const
   608 {
   609   return ByteTagIterator (m_byteTagList.Begin (m_buffer.GetCurrentStartOffset (), m_buffer.GetCurrentEndOffset ()));
   610 }
   611 
   612 bool 
   613 Packet::FindFirstMatchingByteTag (Tag &tag) const
   614 {
   615   TypeId tid = tag.GetInstanceTypeId ();
   616   ByteTagIterator i = GetByteTagIterator ();
   617   while (i.HasNext ())
   618     {
   619       ByteTagIterator::Item item = i.Next ();
   620       if (tid == item.GetTypeId ())
   621         {
   622           item.GetTag (tag);
   623           return true;
   624         }
   625     }
   626   return false;
   627 }
   628 
   629 void 
   630 Packet::AddPacketTag (const Tag &tag) const
   631 {
   632   NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
   633   m_packetTagList.Add (tag);
   634 }
   635 bool 
   636 Packet::RemovePacketTag (Tag &tag)
   637 {
   638   NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
   639   bool found = m_packetTagList.Remove (tag);
   640   return found;
   641 }
   642 bool 
   643 Packet::PeekPacketTag (Tag &tag) const
   644 {
   645   bool found = m_packetTagList.Peek (tag);
   646   return found;
   647 }
   648 void 
   649 Packet::RemoveAllPacketTags (void)
   650 {
   651   NS_LOG_FUNCTION (this);
   652   m_packetTagList.RemoveAll ();
   653 }
   654 
   655 void 
   656 Packet::PrintPacketTags (std::ostream &os) const
   657 {
   658   PacketTagIterator i = GetPacketTagIterator ();
   659   while (i.HasNext ())
   660     {
   661       PacketTagIterator::Item item = i.Next ();
   662       NS_ASSERT (item.GetTypeId ().HasConstructor ());
   663       Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
   664       NS_ASSERT (!constructor.IsNull ());
   665       ObjectBase *instance = constructor ();
   666       Tag *tag = dynamic_cast<Tag *> (instance);
   667       NS_ASSERT (tag != 0);
   668       item.GetTag (*tag);
   669       tag->Print (os);
   670       delete tag;
   671       if (i.HasNext ())
   672         {
   673           os << " ";
   674         }
   675     }
   676 }
   677 
   678 PacketTagIterator 
   679 Packet::GetPacketTagIterator (void) const
   680 {
   681   return PacketTagIterator (m_packetTagList.Head ());
   682 }
   683 
   684 std::ostream& operator<< (std::ostream& os, const Packet &packet)
   685 {
   686   packet.Print (os);
   687   return os;
   688 }
   689 
   690 //-----------------------------------------------------------------------------
   691 // Unit tests
   692 //-----------------------------------------------------------------------------
   693 namespace {
   694 
   695 class ATestTagBase : public Tag
   696 {
   697 public:
   698   ATestTagBase () : m_error (false) {}
   699   bool m_error;
   700 };
   701 
   702 template <int N>
   703 class ATestTag : public ATestTagBase
   704 {
   705 public:
   706   static TypeId GetTypeId (void) {
   707     std::ostringstream oss;
   708     oss << "anon::ATestTag<" << N << ">";
   709     static TypeId tid = TypeId (oss.str ().c_str ())
   710       .SetParent<Tag> ()
   711       .AddConstructor<ATestTag<N> > ()
   712       .HideFromDocumentation ()
   713       ;
   714     return tid;
   715   }
   716   virtual TypeId GetInstanceTypeId (void) const {
   717     return GetTypeId ();
   718   }
   719   virtual uint32_t GetSerializedSize (void) const {
   720     return N;
   721   }
   722   virtual void Serialize (TagBuffer buf) const {
   723     for (uint32_t i = 0; i < N; ++i)
   724       {
   725         buf.WriteU8 (N);
   726       }
   727   }
   728   virtual void Deserialize (TagBuffer buf) {
   729     for (uint32_t i = 0; i < N; ++i)
   730       {
   731         uint8_t v = buf.ReadU8 ();
   732         if (v != N)
   733           {
   734             m_error = true;
   735           }
   736       }
   737   }
   738   virtual void Print (std::ostream &os) const {
   739     os << N;
   740   }
   741   ATestTag ()
   742     : ATestTagBase () {}
   743 };
   744 
   745 class ATestHeaderBase : public Header
   746 {
   747 public:
   748   ATestHeaderBase () : Header (), m_error (false) {}
   749   bool m_error;
   750 };
   751 
   752 template <int N>
   753 class ATestHeader : public ATestHeaderBase
   754 {
   755 public:
   756   static TypeId GetTypeId (void) {
   757     std::ostringstream oss;
   758     oss << "anon::ATestHeader<" << N << ">";
   759     static TypeId tid = TypeId (oss.str ().c_str ())
   760       .SetParent<Header> ()
   761       .AddConstructor<ATestHeader<N> > ()
   762       .HideFromDocumentation ()
   763       ;
   764     return tid;
   765   }
   766   virtual TypeId GetInstanceTypeId (void) const {
   767     return GetTypeId ();
   768   }
   769   virtual uint32_t GetSerializedSize (void) const {
   770     return N;
   771   }
   772   virtual void Serialize (Buffer::Iterator iter) const {
   773     for (uint32_t i = 0; i < N; ++i)
   774       {
   775         iter.WriteU8 (N);
   776       }
   777   }
   778   virtual uint32_t Deserialize (Buffer::Iterator iter) {
   779     for (uint32_t i = 0; i < N; ++i)
   780       {
   781         uint8_t v = iter.ReadU8 ();
   782         if (v != N)
   783           {
   784             m_error = true;
   785           }
   786       }
   787     return N;
   788   }
   789   virtual void Print (std::ostream &os) const {
   790   }
   791   ATestHeader ()
   792     : ATestHeaderBase () {}
   793 
   794 };
   795 
   796 class ATestTrailerBase : public Trailer
   797 {
   798 public:
   799   ATestTrailerBase () : Trailer (), m_error (false) {}
   800   bool m_error;
   801 };
   802 
   803 template <int N>
   804 class ATestTrailer : public ATestTrailerBase
   805 {
   806 public:
   807   static TypeId GetTypeId (void) {
   808     std::ostringstream oss;
   809     oss << "anon::ATestTrailer<" << N << ">";
   810     static TypeId tid = TypeId (oss.str ().c_str ())
   811       .SetParent<Header> ()
   812       .AddConstructor<ATestTrailer<N> > ()
   813       .HideFromDocumentation ()
   814       ;
   815     return tid;
   816   }
   817   virtual TypeId GetInstanceTypeId (void) const {
   818     return GetTypeId ();
   819   }
   820   virtual uint32_t GetSerializedSize (void) const {
   821     return N;
   822   }
   823   virtual void Serialize (Buffer::Iterator iter) const {
   824     iter.Prev (N);
   825     for (uint32_t i = 0; i < N; ++i)
   826       {
   827         iter.WriteU8 (N);
   828       }
   829   }
   830   virtual uint32_t Deserialize (Buffer::Iterator iter) {
   831     iter.Prev (N);
   832     for (uint32_t i = 0; i < N; ++i)
   833       {
   834         uint8_t v = iter.ReadU8 ();
   835         if (v != N)
   836           {
   837             m_error = true;
   838           }
   839       }
   840     return N;
   841   }
   842   virtual void Print (std::ostream &os) const {
   843   }
   844   ATestTrailer ()
   845     : ATestTrailerBase () {}
   846 
   847 };
   848 
   849 
   850 struct Expected
   851 {
   852   Expected (uint32_t n_, uint32_t start_, uint32_t end_)
   853     : n (n_), start (start_), end (end_) {}
   854   
   855   uint32_t n;
   856   uint32_t start;
   857   uint32_t end;
   858 };
   859 
   860 }
   861 
   862 // tag name, start, end
   863 #define E(a,b,c) a,b,c
   864 
   865 #define CHECK(p, n, ...)                                \
   866   DoCheck (p, __FILE__, __LINE__, n, __VA_ARGS__)
   867 
   868 class PacketTest: public TestCase 
   869 {
   870 public:
   871   PacketTest ();
   872   virtual bool DoRun (void);
   873 private:
   874   void DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...);
   875 };
   876 
   877 
   878 PacketTest::PacketTest ()
   879   : TestCase ("Packet") {}
   880 
   881 void
   882 PacketTest::DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...)
   883 {
   884   std::vector<struct Expected> expected;
   885   va_list ap;
   886   va_start (ap, n);
   887   for (uint32_t k = 0; k < n; ++k)
   888     {
   889       uint32_t N = va_arg (ap, uint32_t);
   890       uint32_t start = va_arg (ap, uint32_t);
   891       uint32_t end = va_arg (ap, uint32_t);
   892       expected.push_back (Expected (N, start, end));
   893     }
   894   va_end (ap);
   895 
   896   ByteTagIterator i = p->GetByteTagIterator ();
   897   uint32_t j = 0;
   898   while (i.HasNext () && j < expected.size ())
   899     {
   900       ByteTagIterator::Item item = i.Next ();
   901       struct Expected e = expected[j];
   902       std::ostringstream oss;
   903       oss << "anon::ATestTag<" << e.n << ">";
   904       NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetTypeId ().GetName (), oss.str (), "trivial", file, line);
   905       NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetStart (), e.start, "trivial", file, line);
   906       NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetEnd (), e.end, "trivial", file, line);
   907       ATestTagBase *tag = dynamic_cast<ATestTagBase *> (item.GetTypeId ().GetConstructor () ());
   908       NS_TEST_EXPECT_MSG_NE (tag, 0, "trivial");
   909       item.GetTag (*tag);
   910       NS_TEST_EXPECT_MSG_EQ (tag->m_error, false, "trivial");
   911       delete tag;
   912       j++;
   913     }
   914   NS_TEST_EXPECT_MSG_EQ (i.HasNext (), false, "Nothing left");
   915   NS_TEST_EXPECT_MSG_EQ (j, expected.size (), "Size match");
   916 }
   917 
   918 bool
   919 PacketTest::DoRun (void)
   920 {
   921   Ptr<Packet> pkt1 = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello"), 5);
   922   Ptr<Packet> pkt2 = Create<Packet> (reinterpret_cast<const uint8_t*> (" world"), 6);
   923   Ptr<Packet> packet = Create<Packet> ();
   924   packet->AddAtEnd (pkt1);
   925   packet->AddAtEnd (pkt2);
   926   
   927   NS_TEST_EXPECT_MSG_EQ (packet->GetSize (), 11, "trivial");
   928 
   929   std::string msg = std::string (reinterpret_cast<const char *>(packet->PeekData ()),
   930                                  packet->GetSize ());
   931   NS_TEST_EXPECT_MSG_EQ (msg, "hello world", "trivial");
   932 
   933 
   934   Ptr<const Packet> p = Create<Packet> (1000);
   935 
   936   p->AddByteTag (ATestTag<1> ());
   937   CHECK (p, 1, E (1, 0, 1000));
   938   Ptr<const Packet> copy = p->Copy ();
   939   CHECK (copy, 1, E (1, 0, 1000));
   940 
   941   p->AddByteTag (ATestTag<2> ());
   942   CHECK (p, 2, E (1, 0, 1000), E(2, 0, 1000));
   943   CHECK (copy, 1, E (1, 0, 1000));
   944 
   945   {
   946     Packet c0 = *copy;
   947     Packet c1 = *copy;
   948     c0 = c1;
   949     CHECK (&c0, 1, E (1, 0, 1000));
   950     CHECK (&c1, 1, E (1, 0, 1000));
   951     CHECK (copy, 1, E (1, 0, 1000));
   952     c0.AddByteTag (ATestTag<10> ());
   953     CHECK (&c0, 2, E (1, 0, 1000), E (10, 0, 1000));
   954     CHECK (&c1, 1, E (1, 0, 1000));
   955     CHECK (copy, 1, E (1, 0, 1000));
   956   }
   957 
   958   Ptr<Packet> frag0 = p->CreateFragment (0, 10);
   959   Ptr<Packet> frag1 = p->CreateFragment (10, 90);
   960   Ptr<const Packet> frag2 = p->CreateFragment (100, 900);
   961   frag0->AddByteTag (ATestTag<3> ());
   962   CHECK (frag0, 3, E (1, 0, 10), E(2, 0, 10), E (3, 0, 10));
   963   frag1->AddByteTag (ATestTag<4> ());
   964   CHECK (frag1, 3, E (1, 0, 90), E(2, 0, 90), E (4, 0, 90));
   965   frag2->AddByteTag (ATestTag<5> ());
   966   CHECK (frag2, 3, E (1, 0, 900), E(2, 0, 900), E (5, 0, 900));
   967 
   968   frag1->AddAtEnd (frag2);
   969   CHECK (frag1, 6, E (1, 0, 90), E(2, 0, 90), E (4, 0, 90), E (1, 90, 990), E(2, 90, 990), E (5, 90, 990));
   970 
   971   CHECK (frag0, 3, E (1, 0, 10), E(2, 0, 10), E (3, 0, 10));
   972   frag0->AddAtEnd (frag1);
   973   CHECK (frag0, 9, 
   974          E (1, 0, 10), E(2, 0, 10), E (3, 0, 10),
   975          E (1, 10, 100), E(2, 10, 100), E (4, 10, 100), 
   976          E (1, 100, 1000), E(2, 100, 1000), E (5, 100, 1000));
   977 
   978 
   979   // force caching a buffer of the right size.
   980   frag0 = Create<Packet> (1000);
   981   frag0->AddHeader (ATestHeader<10> ());
   982   frag0 = 0;
   983 
   984   p = Create<Packet> (1000);
   985   p->AddByteTag (ATestTag<20> ());
   986   CHECK (p, 1, E (20, 0, 1000));
   987   frag0 = p->CreateFragment (10, 90);
   988   CHECK (p, 1, E (20, 0, 1000));
   989   CHECK (frag0, 1, E (20, 0, 90));
   990   p = 0;
   991   frag0->AddHeader (ATestHeader<10> ());
   992   CHECK (frag0, 1, E (20, 10, 100));
   993 
   994   {
   995     Ptr<Packet> tmp = Create<Packet> (100);
   996     tmp->AddByteTag (ATestTag<20> ());
   997     CHECK (tmp, 1, E (20, 0, 100));
   998     tmp->AddHeader (ATestHeader<10> ());
   999     CHECK (tmp, 1, E (20, 10, 110));
  1000     ATestHeader<10> h;
  1001     tmp->RemoveHeader (h);
  1002     CHECK (tmp, 1, E (20, 0, 100));
  1003     tmp->AddHeader (ATestHeader<10> ());
  1004     CHECK (tmp, 1, E (20, 10, 110));
  1005 
  1006     tmp = Create<Packet> (100);
  1007     tmp->AddByteTag (ATestTag<20> ());
  1008     CHECK (tmp, 1, E (20, 0, 100));
  1009     tmp->AddTrailer (ATestTrailer<10> ());
  1010     CHECK (tmp, 1, E (20, 0, 100));
  1011     ATestTrailer<10> t;
  1012     tmp->RemoveTrailer (t);
  1013     CHECK (tmp, 1, E (20, 0, 100));
  1014     tmp->AddTrailer (ATestTrailer<10> ());
  1015     CHECK (tmp, 1, E (20, 0, 100));
  1016     
  1017   }
  1018 
  1019   {
  1020     Ptr<Packet> tmp = Create<Packet> (0);
  1021     tmp->AddHeader (ATestHeader<156> ());
  1022     tmp->AddByteTag (ATestTag<20> ());
  1023     CHECK (tmp, 1, E (20, 0, 156));
  1024     tmp->RemoveAtStart (120);
  1025     CHECK (tmp, 1, E (20, 0, 36));
  1026     Ptr<Packet> a = Create<Packet> (0);
  1027     a->AddAtEnd (tmp);
  1028     CHECK (a, 1, E (20, 0, 36));
  1029   }
  1030 
  1031   {
  1032     Ptr<Packet> tmp = Create<Packet> (0);
  1033     tmp->AddByteTag (ATestTag<20> ());
  1034     CHECK (tmp, 0, E (20, 0, 0));
  1035   }
  1036   {
  1037     Ptr<Packet> tmp = Create<Packet> (1000);
  1038     tmp->AddByteTag (ATestTag<20> ());
  1039     CHECK (tmp, 1, E (20, 0, 1000));
  1040     tmp->RemoveAtStart (1000);
  1041     CHECK (tmp, 0,  E (0,0,0));
  1042     Ptr<Packet> a = Create<Packet> (10);
  1043     a->AddByteTag (ATestTag<10> ());
  1044     CHECK (a, 1, E (10, 0, 10));
  1045     tmp->AddAtEnd (a);
  1046     CHECK (tmp, 1, E (10, 0, 10));
  1047   }
  1048 
  1049   {
  1050     Packet p;
  1051     ATestTag<10> a;
  1052     p.AddPacketTag (a);
  1053     NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), true, "trivial");
  1054     ATestTag<11> b;
  1055     p.AddPacketTag (b);
  1056     NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), true, "trivial");
  1057     NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), true, "trivial");
  1058     Packet copy = p;
  1059     NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), true, "trivial");
  1060     NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
  1061     ATestTag<12> c;
  1062     NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), false, "trivial");
  1063     copy.AddPacketTag (c);
  1064     NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), true, "trivial");
  1065     NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), true, "trivial");
  1066     NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
  1067     NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (c), false, "trivial");
  1068     copy.RemovePacketTag (b);
  1069     NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), false, "trivial");
  1070     NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), true, "trivial");
  1071     p.RemovePacketTag (a);
  1072     NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), false, "trivial");
  1073     NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
  1074     NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (c), false, "trivial");
  1075     NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), true, "trivial");
  1076     p.RemoveAllPacketTags ();
  1077     NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), false, "trivial");
  1078   }
  1079 
  1080   {
  1081     // bug 572                                                                  
  1082     Ptr<Packet> tmp = Create<Packet> (1000);
  1083     tmp->AddByteTag (ATestTag<20> ());
  1084     CHECK (tmp, 1, E (20, 0, 1000));
  1085     tmp->AddHeader (ATestHeader<2> ());
  1086     CHECK (tmp, 1, E (20, 2, 1002));
  1087     tmp->RemoveAtStart (1);
  1088     CHECK (tmp, 1, E (20, 1, 1001));
  1089     tmp->PeekData ();
  1090     CHECK (tmp, 1, E (20, 1, 1001));
  1091   }
  1092 
  1093   return GetErrorStatus ();
  1094 }
  1095 //-----------------------------------------------------------------------------
  1096 class PacketTestSuite : public TestSuite
  1097 {
  1098 public:
  1099   PacketTestSuite ();
  1100 };
  1101 
  1102 PacketTestSuite::PacketTestSuite ()
  1103   : TestSuite ("packet", UNIT)
  1104 {
  1105   AddTestCase (new PacketTest);
  1106 }
  1107 
  1108 PacketTestSuite g_packetTestSuite;
  1109 
  1110 
  1111 } // namespace ns3