implement PacketHistory::RemoveAtStart
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Wed, 06 Jun 2007 08:49:15 +0200
changeset 845 7abb0f867d8f
parent 844 d17e2aca5a17
child 846 cf1ae24de38a
implement PacketHistory::RemoveAtStart
src/common/packet-history.cc
src/common/packet-history.h
--- a/src/common/packet-history.cc	Tue Jun 05 21:48:26 2007 +0200
+++ b/src/common/packet-history.cc	Wed Jun 06 08:49:15 2007 +0200
@@ -660,6 +660,91 @@
 }
 
 void
+PacketHistory::AddBig (bool atStart,
+                       const PacketHistory::SmallItem *item, 
+                       const PacketHistory::ExtraItem *extraItem)
+{
+  if (m_data == 0)
+    {
+      m_data = PacketHistory::Create (10);
+      memset (m_data->m_data, 0xff, 4);
+    }
+  NS_ASSERT (m_data != 0);
+ append:
+  uint8_t *start = &m_data->m_data[m_used];
+  uint8_t *end = &m_data->m_data[m_data->m_size];
+  if (end - start >= 13 &&
+      CanAdd (atStart) &&
+      (m_data->m_count == 1 ||
+       m_used == m_data->m_dirtyEnd))
+    {
+      uint8_t *buffer = start;
+      uint16_t next, prev;
+      if (atStart)
+        {
+          next = m_head;
+          prev = 0xffff;
+        }
+      else
+        {
+          next = 0xffff;
+          prev = m_tail;
+        }
+
+      Append16 (next, &buffer);
+      Append16 (prev, &buffer);
+      if (TryToAppend (item->typeUid, &buffer, end) &&
+          TryToAppend (item->size, &buffer, end) &&
+          TryToAppend (item->chunkUid, &buffer, end) &&
+          TryToAppend (extraItem->fragmentStart, &buffer, end) &&
+          TryToAppend (extraItem->fragmentEnd, &buffer, end) &&
+          TryToAppend (extraItem->packetUid, &buffer, end))
+        {
+          uintptr_t written = buffer - start;
+          NS_ASSERT (written <= 0xffff);
+          if (m_head == 0xffff)
+            {
+              NS_ASSERT (m_tail == 0xffff);
+              m_head = m_used;
+              m_tail = m_used;
+            } 
+          else if (atStart)
+            {
+              NS_ASSERT (m_head != 0xffff);
+              // overwrite the prev field of the previous head of the list.
+              uint8_t *previousHead = &m_data->m_data[m_head] + 2;
+              Append16 (m_used, &previousHead);
+              // update the head of list to the new node.
+              m_head = m_used;
+            }
+          else
+            {
+              NS_ASSERT (m_tail != 0xffff);
+              // overwrite the next field of the previous tail of the list.
+              uint8_t *previousTail = &m_data->m_data[m_tail];
+              Append16 (m_used, &previousTail);
+              // update the tail of the list to the new node.
+              m_tail = m_used;
+            }
+          NS_ASSERT (m_tail != 0xffff);
+          NS_ASSERT (m_head != 0xffff);
+          m_used += written;
+          m_data->m_dirtyEnd = m_used;
+          return;
+        }
+    }
+  
+  uint32_t n = GetUleb128Size (item->typeUid);
+  n += GetUleb128Size (item->size);
+  n += GetUleb128Size (item->chunkUid);
+  n += 2 + 2;
+  ReserveCopy (n);
+  goto append;
+
+}
+
+
+void
 PacketHistory::ReadSmall (struct PacketHistory::SmallItem *item, const uint8_t **pBuffer) const
 {
   const uint8_t *buffer = *pBuffer;
@@ -877,15 +962,60 @@
     {
       return;
     }
-#if 0
   if (m_data == 0)
     {
-      NS_FATAL_ERROR ("Removing header from empty packet.");
+      NS_FATAL_ERROR ("Removing data from start of empty packet.");
     }
+
+  uint32_t leftToRemove = start;
+  uint16_t current = m_head;
+  uint16_t tail = m_tail;
+  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;
+      PacketHistory::ExtraItem extraItem;
+      if (isExtra)
+        {
+          ReadExtra (&extraItem, &buffer);
+        }
+      else
+        {
+          extraItem.fragmentStart = 0;
+          extraItem.fragmentEnd = item.size;
+          extraItem.packetUid = m_packetUid;
+        }
+      uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
+      if (itemRealSize <= leftToRemove)
+        {
+          // remove from list.
+          m_head = item.next;
+          leftToRemove -= itemRealSize;
+        }
+      else
+        {
+          // fragment the list item.
+          PacketHistory fragment (m_packetUid, 0);
+          extraItem.fragmentStart += leftToRemove;
+          leftToRemove = 0;
+          fragment.AddBig (false, &item, &extraItem);
+          NS_ASSERT (item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
+                     extraItem.fragmentStart <= extraItem.fragmentEnd);
+        }
+      if (current == tail)
+        {
+          break;
+        }
+      current = item.next;
+    }
+  NS_ASSERT (leftToRemove == 0);
+#if 0
   struct PacketHistory::SmallItem item;
-  uint8_t *buffer = &m_data->m_data[m_head];
-  bool ok = ReadSmall (&item, &buffer);
-  NS_ASSERT (ok);
+  const uint8_t *buffer = &m_data->m_data[m_head];
+  ReadSmall (&item, &buffer);
+  NS_ASSERT (buffer <= &m_data->m_data[m_data->m_size]);
   if ((item.typeUid & 0xfffffffe) != uid ||
       item.size != size)
     {
@@ -895,14 +1025,19 @@
     {
       // this is a "big" item
       struct PacketHistory::ExtraItem extraItem;
-      ok = ReadExtra (&extraItem, &buffer);
-      NS_ASSERT (ok);
+      ReadExtra (&extraItem, &buffer);
+      NS_ASSERT (buffer <= &m_data->m_data[m_data->m_size]);
       if (extraItem.fragmentStart != 0 ||
           extraItem.fragmentEnd != size)
         {
           NS_FATAL_ERROR ("Removing incomplete header.");
         }
     }
+  m_head = item.next;
+  if (m_head > m_tail)
+    {
+      m_used = m_head;
+    }
 
   uint32_t leftToRemove = start;
   while (!m_itemList.empty () && leftToRemove > 0)
@@ -1545,7 +1680,10 @@
   p1.RemoveAtStart (3);
   CHECK_HISTORY (p1, 4, 
                  2, 1, 10, 4);
-  p1.RemoveAtStart (2);
+  p1.RemoveAtStart (1);
+  CHECK_HISTORY (p1, 4, 
+                 1, 1, 10, 4);
+  p1.RemoveAtStart (1);
   CHECK_HISTORY (p1, 3, 
                  1, 10, 4);
   p1.RemoveAtEnd (4);
--- a/src/common/packet-history.h	Tue Jun 05 21:48:26 2007 +0200
+++ b/src/common/packet-history.h	Wed Jun 06 08:49:15 2007 +0200
@@ -100,6 +100,9 @@
 
   void AddSmall (bool atStart,
                  uint32_t typeUid, uint32_t size);
+  void AddBig (bool atStart,
+               const PacketHistory::SmallItem *item, 
+               const PacketHistory::ExtraItem *extraItem);
   uint32_t GetUleb128Size (uint32_t value) const;
   uint32_t ReadUleb128 (const uint8_t **pBuffer) const;
   void Append16 (uint16_t value, uint8_t **pBuffer);