implement PacketHistory::Print
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Tue, 05 Jun 2007 15:47:29 +0200
changeset 837 b73b63e84130
parent 836 f9f5f66013cc
child 838 186decaef5c2
implement PacketHistory::Print
src/common/packet-history.cc
src/common/packet-history.h
src/common/packet-printer.cc
src/common/packet-printer.h
--- a/src/common/packet-history.cc	Tue Jun 05 14:06:58 2007 +0200
+++ b/src/common/packet-history.cc	Tue Jun 05 15:47:29 2007 +0200
@@ -331,8 +331,8 @@
 
 PacketHistory::PacketHistory (uint32_t uid, uint32_t size)
   : m_data (0),
-    m_begin (0),
-    m_end (0),
+    m_begin (0xffff),
+    m_end (0xffff),
     m_used (0),
     m_packetUid (uid)
 {
@@ -436,9 +436,9 @@
   return n;
 }
 uint32_t
-PacketHistory::ReadUleb128 (uint8_t **pBuffer) const
+PacketHistory::ReadUleb128 (const uint8_t **pBuffer) const
 {
-  uint8_t *buffer = *pBuffer;
+  const uint8_t *buffer = *pBuffer;
   uint32_t result = 0;
   uint8_t byte;
   result = 0;
@@ -540,21 +540,25 @@
 }
 
 bool
-PacketHistory::IsZero16 (uint16_t index)
+PacketHistory::IsFF16 (uint16_t index)
 {
-  return m_data->m_data[index] == 0 && m_data->m_data[index+1] == 0;
+  return m_data->m_data[index] == 0xff && m_data->m_data[index+1] == 0xff;
 }
 
 bool
 PacketHistory::CanAdd (bool atStart)
 {
-  if (atStart)
+  if (atStart && m_begin != 0xffff)
     {
-      return IsZero16 (m_begin+2);
+      return IsFF16 (m_begin+2);
+    }
+  else if (!atStart && m_end != 0xffff)
+    {
+      return IsFF16 (m_end);
     }
   else
     {
-      return IsZero16 (m_end);
+      return false;
     }
 }
 
@@ -565,7 +569,7 @@
   if (m_data == 0)
     {
       m_data = PacketHistory::Create (10);
-      memset (m_data->m_data, 0, 4);
+      memset (m_data->m_data, 0xff, 4);
     }
   NS_ASSERT (m_data != 0);
   uint16_t chunkUid = m_chunkUid;
@@ -583,11 +587,11 @@
       if (atStart)
         {
           next = m_begin;
-          prev = 0;
+          prev = 0xffff;
         }
       else
         {
-          next = 0;
+          next = 0xffff;
           prev = m_end;
         }
 
@@ -599,7 +603,13 @@
         {
           uintptr_t written = buffer - start;
           NS_ASSERT (written <= 0xffff);
-          if (atStart)
+          if (m_begin == 0xffff)
+            {
+              NS_ASSERT (m_end == 0xffff);
+              m_begin = m_used;
+              m_end = m_used;
+            } 
+          else if (atStart)
             {
               m_begin = m_used;
             }
@@ -607,6 +617,8 @@
             {
               m_end = m_used;
             }
+          NS_ASSERT (m_end != 0xffff);
+          NS_ASSERT (m_begin != 0xffff);
           m_used += written;
           m_data->m_dirtyEnd = m_used;
           return;
@@ -622,9 +634,9 @@
 }
 
 void
-PacketHistory::ReadSmall (struct PacketHistory::SmallItem *item, uint8_t **pBuffer)
+PacketHistory::ReadSmall (struct PacketHistory::SmallItem *item, const uint8_t **pBuffer) const
 {
-  uint8_t *buffer = *pBuffer;
+  const uint8_t *buffer = *pBuffer;
   item->next = buffer[0];
   item->next |= (buffer[1]) << 8;
   item->prev = buffer[2];
@@ -636,7 +648,7 @@
 }
 
 void
-PacketHistory::ReadExtra (struct PacketHistory::ExtraItem *item, uint8_t **pBuffer)
+PacketHistory::ReadExtra (struct PacketHistory::ExtraItem *item, const uint8_t **pBuffer) const
 {
   item->fragmentStart = ReadUleb128 (pBuffer);
   item->fragmentEnd = ReadUleb128 (pBuffer);
@@ -743,7 +755,7 @@
       NS_FATAL_ERROR ("Removing header from empty packet.");
     }
   struct PacketHistory::SmallItem item;
-  uint8_t *buffer = &m_data->m_data[m_begin];
+  const uint8_t *buffer = &m_data->m_data[m_begin];
   ReadSmall (&item, &buffer);
   NS_ASSERT (buffer < &m_data->m_data[m_data->m_size]);
   if ((item.typeUid & 0xfffffffd) != uid ||
@@ -790,7 +802,7 @@
       NS_FATAL_ERROR ("Removing trailer from empty packet.");
     }
   struct PacketHistory::SmallItem item;
-  uint8_t *buffer = &m_data->m_data[m_end];
+  const uint8_t *buffer = &m_data->m_data[m_end];
   ReadSmall (&item, &buffer);
   NS_ASSERT (buffer < &m_data->m_data[m_data->m_size]);
   if ((item.typeUid & 0xfffffffd) != uid ||
@@ -902,14 +914,148 @@
   Print (os, buffer, PacketPrinter::GetDefault ());
 }
 
+uint32_t
+PacketHistory::DoPrint (struct PacketHistory::SmallItem *item, uint8_t const*buffer,
+                        Buffer data, uint32_t offset, const PacketPrinter &printer,
+                        std::ostream &os) const
+{
+  ReadSmall (item, &buffer);
+  bool isExtra = (item->typeUid & 0x1) == 0x1;
+  uint32_t uid = item->typeUid & 0xfffffffd;
+  uint32_t fragmentStart, fragmentEnd;
+  uint32_t packetUid;
+  if (isExtra)
+    {
+      PacketHistory::ExtraItem extraItem;
+      ReadExtra (&extraItem, &buffer);
+      fragmentStart = extraItem.fragmentStart;
+      fragmentEnd = extraItem.fragmentEnd;
+      packetUid = extraItem.packetUid;
+    }
+  else
+    {
+      fragmentStart = 0;
+      fragmentEnd = item->size;
+      packetUid = m_packetUid;
+    }
+  NS_ASSERT (buffer < &m_data->m_data[m_data->m_size]);
+  if (uid == 0)
+    {
+      // payload.
+      printer.PrintPayload (os, packetUid, item->size, 
+                            fragmentStart, 
+                            fragmentEnd);
+    }
+  else if (fragmentStart != 0 && 
+           fragmentEnd != item->size)
+    {
+      printer.PrintChunkFragment (uid, os, packetUid, item->size, 
+                                  fragmentStart, fragmentEnd);
+    }
+  else if (PacketPrinter::IsHeader (uid))
+    {
+      ns3::Buffer::Iterator j = data.Begin ();
+      j.Next (offset);
+      printer.PrintChunk (uid, j, os, packetUid, item->size);
+    }
+  else if (PacketPrinter::IsTrailer (uid))
+    {
+      ns3::Buffer::Iterator j = data.End ();
+      j.Prev (data.GetSize () - (offset + item->size));
+      printer.PrintChunk (uid, j, os, packetUid, item->size);
+    }
+  else 
+    {
+      NS_ASSERT (false);
+    }
+  return fragmentEnd - fragmentStart;
+}
+
+uint32_t
+PacketHistory::GetTotalSize (void) const
+{
+  uint32_t totalSize = 0;
+  uint16_t current = m_begin;
+  uint16_t end = m_end;
+  while (current != 0xffff)
+    {
+      const uint8_t *buffer = &m_data->m_data[current];
+      struct PacketHistory::SmallItem item;
+      ReadSmall (&item, &buffer);
+      bool isExtra = (item.typeUid & 0x1) == 0x1;
+      uint32_t fragmentStart, fragmentEnd;
+      if (isExtra)
+        {
+          PacketHistory::ExtraItem extraItem;
+          ReadExtra (&extraItem, &buffer);
+          fragmentStart = extraItem.fragmentStart;
+          fragmentEnd = extraItem.fragmentEnd;
+        }
+      else
+        {
+          fragmentStart = 0;
+          fragmentEnd = item.size;
+        }
+      totalSize += fragmentEnd - fragmentStart;
+      current = item.next;
+      if (current == end)
+        {
+          break;
+        }
+    }
+  return totalSize;
+}
+
 void
-PacketHistory::Print (std::ostream &os, Buffer buffer, const PacketPrinter &printer) const
+PacketHistory::Print (std::ostream &os, Buffer data, const PacketPrinter &printer) const
 {
   if (!m_enable) 
     {
       return;
     }
-
+  if (m_data == 0)
+    {
+      return;
+    }
+  NS_ASSERT (GetTotalSize () == data.GetSize ());
+  if (printer.m_forward)
+    {
+      uint32_t end = m_end;
+      uint32_t begin = m_begin;
+      uint32_t current = begin;
+      uint32_t offset = 0;
+      while (current != 0xffff)
+        {
+          uint8_t *buffer = &m_data->m_data[current];
+          struct PacketHistory::SmallItem item;
+          uint32_t realSize = DoPrint (&item, buffer, data, offset, printer, os);
+          offset += realSize;
+          current = item.next;
+          if (current == end)
+            {
+              break;
+            }
+        }
+    }
+  else
+    {
+      uint32_t end = m_begin;
+      uint32_t begin = m_end;
+      uint32_t current = begin;
+      uint32_t offset = 0;
+      while (current != 0xffff)
+        {
+          uint8_t *buffer = &m_data->m_data[current];
+          struct PacketHistory::SmallItem item;
+          uint32_t realSize = DoPrint (&item, buffer, data, offset, printer, os);
+          offset -= realSize;
+          current = item.prev;
+          if (current == end)
+            {
+              break;
+            }
+        }
+    }
 }
 
 
@@ -1117,8 +1263,8 @@
   static bool registered = false;
   if (!registered)
     {
-      m_printer.AddPrinter (MakeCallback (&PacketHistoryTest::PrintHeader<N>, this),
-                            MakeCallback (&PacketHistoryTest::PrintFragment, this));
+      m_printer.AddHeaderPrinter (MakeCallback (&PacketHistoryTest::PrintHeader<N>, this),
+                                  MakeCallback (&PacketHistoryTest::PrintFragment, this));
       registered = true;
     }
 }
@@ -1130,8 +1276,8 @@
   static bool registered = false;
   if (!registered)
     {
-      m_printer.AddPrinter (MakeCallback (&PacketHistoryTest::PrintTrailer<N>, this),
-                            MakeCallback (&PacketHistoryTest::PrintFragment, this));
+      m_printer.AddTrailerPrinter (MakeCallback (&PacketHistoryTest::PrintTrailer<N>, this),
+                                   MakeCallback (&PacketHistoryTest::PrintFragment, this));
       registered = true;
     }
 }
--- a/src/common/packet-history.h	Tue Jun 05 14:06:58 2007 +0200
+++ b/src/common/packet-history.h	Tue Jun 05 15:47:29 2007 +0200
@@ -96,15 +96,19 @@
   void AddSmall (bool atStart,
                  uint32_t typeUid, uint32_t size);
   uint32_t GetUleb128Size (uint32_t value) const;
-  uint32_t ReadUleb128 (uint8_t **pBuffer) const;
+  uint32_t ReadUleb128 (const uint8_t **pBuffer) const;
   void Append16 (uint16_t value, uint8_t **pBuffer);
   bool TryToAppend (uint32_t value, uint8_t **pBuffer, uint8_t *end);
-  bool IsZero16 (uint16_t index);
+  bool IsFF16 (uint16_t index);
   bool CanAdd (bool atStart);
-  void ReadSmall (struct PacketHistory::SmallItem *item, uint8_t **pBuffer);
-  void ReadExtra (struct PacketHistory::ExtraItem *item, uint8_t **pBuffer);
+  void ReadSmall (struct PacketHistory::SmallItem *item, const uint8_t **pBuffer) const;
+  void ReadExtra (struct PacketHistory::ExtraItem *item, const uint8_t **pBuffer) const;
   void Reserve (uint32_t n);
   void ReserveCopy (uint32_t n);
+  uint32_t DoPrint (struct PacketHistory::SmallItem *item, uint8_t const*buffer,
+                    Buffer data, uint32_t offset, const PacketPrinter &printer,
+                    std::ostream &os) const;
+  uint32_t GetTotalSize (void) const;
 
   static struct PacketHistory::Data *Create (uint32_t size);
   static void Recycle (struct PacketHistory::Data *data);
@@ -131,26 +135,26 @@
 void 
 PacketHistory::AddHeader (T const &header, uint32_t size)
 {
-  AddHeader (PacketPrinter::GetUid<T> (), header, size);
+  AddHeader (PacketPrinter::GetHeaderUid<T> (), header, size);
 }
 
 template <typename T>
 void 
 PacketHistory::RemoveHeader (T const &header, uint32_t size)
 {
-  RemoveHeader (PacketPrinter::GetUid<T> (), header, size);
+  RemoveHeader (PacketPrinter::GetHeaderUid<T> (), header, size);
 }
 template <typename T>
 void 
 PacketHistory::AddTrailer (T const &trailer, uint32_t size)
 {
-  AddTrailer (PacketPrinter::GetUid<T> (), trailer, size);
+  AddTrailer (PacketPrinter::GetTrailerUid<T> (), trailer, size);
 }
 template <typename T>
 void 
 PacketHistory::RemoveTrailer (T const &trailer, uint32_t size)
 {
-  RemoveTrailer (PacketPrinter::GetUid<T> (), trailer, size);
+  RemoveTrailer (PacketPrinter::GetTrailerUid<T> (), trailer, size);
 }
 
 }; // namespace ns3
--- a/src/common/packet-printer.cc	Tue Jun 05 14:06:58 2007 +0200
+++ b/src/common/packet-printer.cc	Tue Jun 05 15:47:29 2007 +0200
@@ -87,12 +87,12 @@
     {
       if (i->m_chunkUid == chunkUid)
         {
-          DoPrintCallback cb = (*registeredChunks)[chunkUid-1].first;
+          DoPrintCallback cb = (*registeredChunks)[chunkUid/2-1].printCallback;
           cb (i->m_printer, start, os, packetUid, size);
           return;
         }
     }
-  DoGetNameCallback cb = (*registeredChunks)[chunkUid-1].second;
+  DoGetNameCallback cb = (*registeredChunks)[chunkUid-1].getNameCallback;
   std::string name = cb ();
   struct PacketPrinter::FragmentInformation info;
   info.start = 0;
@@ -109,7 +109,7 @@
 {
   RegisteredChunks *registeredChunks = PacketPrinter::GetRegisteredChunks ();
   NS_ASSERT (chunkUid >= 1);
-  DoGetNameCallback cb = (*registeredChunks)[chunkUid-1].second;
+  DoGetNameCallback cb = (*registeredChunks)[chunkUid/2-1].getNameCallback;
   std::string name = cb ();
   struct PacketPrinter::FragmentInformation info;
   info.start = fragmentStart;
@@ -186,5 +186,23 @@
   m_printerList.push_back (p);
 }
 
+bool 
+PacketPrinter::IsTrailer (uint32_t uid)
+{
+  RegisteredChunks *registeredChunks = PacketPrinter::GetRegisteredChunks ();
+  NS_ASSERT (uid >= 1 && uid/2 < registeredChunks->size ());
+  bool isHeader = (*registeredChunks)[uid/2-1].isHeader;
+  return !isHeader;
+}
+bool 
+PacketPrinter::IsHeader (uint32_t uid)
+{
+  RegisteredChunks *registeredChunks = PacketPrinter::GetRegisteredChunks ();
+  NS_ASSERT (uid >= 1 && uid/2 < registeredChunks->size ());
+  bool isHeader = (*registeredChunks)[uid/2-1].isHeader;
+  return isHeader;
+}
+
+
 
 } // namespace ns3
--- a/src/common/packet-printer.h	Tue Jun 05 14:06:58 2007 +0200
+++ b/src/common/packet-printer.h	Tue Jun 05 15:47:29 2007 +0200
@@ -85,8 +85,15 @@
    * \param fragmentPrinter printer for a fragment of the specified chunk
    */
   template <typename T>
-  void AddPrinter (Callback<void,std::ostream &,uint32_t,uint32_t,const T *> printer,
-		   ChunkFragmentPrinter fragmentPrinter);
+  void AddHeaderPrinter (Callback<void,std::ostream &,uint32_t,uint32_t,const T *> printer,
+                         ChunkFragmentPrinter fragmentPrinter);
+  /**
+   * \param printer printer for the specified chunk
+   * \param fragmentPrinter printer for a fragment of the specified chunk
+   */
+  template <typename T>
+  void AddTrailerPrinter (Callback<void,std::ostream &,uint32_t,uint32_t,const T *> printer,
+                          ChunkFragmentPrinter fragmentPrinter);
   /**
    * \param printer printer for a chunk for which no callback was specified explicitely
    */
@@ -95,6 +102,9 @@
 private:
   friend class PacketHistory;
   friend class ::ItemList;
+  typedef void (*DoPrintCallback) (Ptr<CallbackImplBase>, Buffer::Iterator, std::ostream &,
+                                   uint32_t, uint32_t);
+  typedef std::string (*DoGetNameCallback) (void);
   struct Printer
   {
     uint32_t m_chunkUid;
@@ -102,11 +112,14 @@
     Callback<void,std::ostream &,uint32_t,uint32_t,std::string &,struct PacketPrinter::FragmentInformation>
       m_fragmentPrinter;
   };
-  typedef void (*DoPrintCallback) (Ptr<CallbackImplBase>, Buffer::Iterator, std::ostream &,
-                                   uint32_t, uint32_t);
-  typedef std::string (*DoGetNameCallback) (void);
+  struct RegisteredChunk
+  {
+    DoPrintCallback printCallback;
+    DoGetNameCallback getNameCallback;
+    bool isHeader;
+  };
   typedef std::vector<struct PacketPrinter::Printer> PrinterList;
-  typedef std::vector<std::pair<DoPrintCallback,DoGetNameCallback> > RegisteredChunks;
+  typedef std::vector<struct RegisteredChunk> RegisteredChunks;
 
 
   static PacketPrinter GetDefault (void);
@@ -138,10 +151,14 @@
   template <typename T>
   static std::string DoGetName (void);
   template <typename T>
-  static uint32_t GetUid (void);
+  static uint32_t GetTrailerUid (void);
+  template <typename T>
+  static uint32_t GetHeaderUid (void);
   template <typename T>
-  static uint32_t AllocateUid (void);
+  static uint32_t AllocateUid (bool isHeader);
   static RegisteredChunks *GetRegisteredChunks (void);
+  static bool IsTrailer (uint32_t uid);
+  static bool IsHeader (uint32_t uid);
 
 
   void PrintChunk (uint32_t uid, 
@@ -179,7 +196,7 @@
 
 template <typename T>
 void 
-PacketPrinter::AddPrinter (Callback<void,std::ostream &, uint32_t, uint32_t, const T *> printer,
+PacketPrinter::AddHeaderPrinter (Callback<void,std::ostream &, uint32_t, uint32_t, const T *> printer,
 			   Callback<void,
 		            std::ostream &, 
 		            uint32_t, 
@@ -187,7 +204,21 @@
                             std::string &,
 		            struct PacketPrinter::FragmentInformation> fragmentPrinter)
 {
-  static uint32_t uid = PacketPrinter::GetUid<T> ();
+  static uint32_t uid = PacketPrinter::GetHeaderUid<T> ();
+  DoAddPrinter (uid, printer.GetImpl (), fragmentPrinter);
+}
+
+template <typename T>
+void 
+PacketPrinter::AddTrailerPrinter (Callback<void,std::ostream &, uint32_t, uint32_t, const T *> printer,
+			   Callback<void,
+		            std::ostream &, 
+		            uint32_t, 
+                            uint32_t, 
+                            std::string &,
+		            struct PacketPrinter::FragmentInformation> fragmentPrinter)
+{
+  static uint32_t uid = PacketPrinter::GetTrailerUid<T> ();
   DoAddPrinter (uid, printer.GetImpl (), fragmentPrinter);
 }
 
@@ -216,20 +247,31 @@
 
 template <typename T>
 uint32_t 
-PacketPrinter::GetUid (void)
+PacketPrinter::GetHeaderUid (void)
 {
-  static uint32_t uid = PacketPrinter::AllocateUid<T> ();
+  static uint32_t uid = PacketPrinter::AllocateUid<T> (true);
+  return uid;
+}
+
+template <typename T>
+uint32_t 
+PacketPrinter::GetTrailerUid (void)
+{
+  static uint32_t uid = PacketPrinter::AllocateUid<T> (false);
   return uid;
 }
 
 template <typename T>
 uint32_t
-PacketPrinter::AllocateUid (void)
+PacketPrinter::AllocateUid (bool isHeader)
 {
   RegisteredChunks *chunks = PacketPrinter::GetRegisteredChunks ();
-  chunks->push_back (std::make_pair(&PacketPrinter::DoPrint<T>, 
-                                    &PacketPrinter::DoGetName<T>));
-  uint32_t uid = chunks->size ();
+  RegisteredChunk chunk;
+  chunk.printCallback = &PacketPrinter::DoPrint<T>;
+  chunk.getNameCallback = &PacketPrinter::DoGetName<T>;
+  chunk.isHeader = isHeader;
+  chunks->push_back (chunk);
+  uint32_t uid = chunks->size () * 2;
   PacketPrinter::PeekDefault ()->DoAddPrinter (uid, 
                                                MakeCallback (&PacketPrinter::DoDefaultPrint<T>).GetImpl (),
                                                MakeCallback (&PacketPrinter::DoDefaultPrintFragment));