A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
buffer.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006,2007 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 "buffer.h"
21 #include "ns3/assert.h"
22 #include "ns3/log.h"
23 
24 NS_LOG_COMPONENT_DEFINE ("Buffer");
25 
26 #define LOG_INTERNAL_STATE(y) \
27  NS_LOG_LOGIC (y << "start="<<m_start<<", end="<<m_end<<", zero start="<<m_zeroAreaStart<< \
28  ", zero end="<<m_zeroAreaEnd<<", count="<<m_data->m_count<<", size="<<m_data->m_size<< \
29  ", dirty start="<<m_data->m_dirtyStart<<", dirty end="<<m_data->m_dirtyEnd)
30 
31 namespace {
32 
33 static struct Zeroes
34 {
35  Zeroes ()
36  : size (1000)
37  {
38  memset (buffer, 0, size);
39  }
40  char buffer[1000];
41  const uint32_t size;
42 } g_zeroes;
43 
44 }
45 
46 namespace ns3 {
47 
48 
49 uint32_t Buffer::g_recommendedStart = 0;
50 #ifdef BUFFER_FREE_LIST
51 /* The following macros are pretty evil but they are needed to allow us to
52  * keep track of 3 possible states for the g_freeList variable:
53  * - uninitialized means that no one has created a buffer yet
54  * so no one has created the associated free list (it is created
55  * on-demand when the first buffer is created)
56  * - initialized means that the free list exists and is valid
57  * - destroyed means that the static destructors of this compilation unit
58  * have run so, the free list has been cleared from its content
59  * The key is that in destroyed state, we are careful not re-create it
60  * which is a typical weakness of lazy evaluation schemes which use
61  * '0' as a special value to indicate both un-initialized and destroyed.
62  * Note that it is important to use '0' as the marker for un-initialized state
63  * because the variable holding this state information is initialized to zero
64  * which the compiler assigns to zero-memory which is initialized to _zero_
65  * before the constructors run so this ensures perfect handling of crazy
66  * constructor orderings.
67  */
68 #define MAGIC_DESTROYED (~(long) 0)
69 #define IS_UNINITIALIZED(x) (x == (Buffer::FreeList*)0)
70 #define IS_DESTROYED(x) (x == (Buffer::FreeList*)MAGIC_DESTROYED)
71 #define IS_INITIALIZED(x) (!IS_UNINITIALIZED (x) && !IS_DESTROYED (x))
72 #define DESTROYED ((Buffer::FreeList*)MAGIC_DESTROYED)
73 #define UNINITIALIZED ((Buffer::FreeList*)0)
74 uint32_t Buffer::g_maxSize = 0;
75 Buffer::FreeList *Buffer::g_freeList = 0;
76 struct Buffer::LocalStaticDestructor Buffer::g_localStaticDestructor;
77 
78 Buffer::LocalStaticDestructor::~LocalStaticDestructor(void)
79 {
80  NS_LOG_FUNCTION (this);
81  if (IS_INITIALIZED (g_freeList))
82  {
83  for (Buffer::FreeList::iterator i = g_freeList->begin ();
84  i != g_freeList->end (); i++)
85  {
86  Buffer::Deallocate (*i);
87  }
88  delete g_freeList;
89  g_freeList = DESTROYED;
90  }
91 }
92 
93 void
94 Buffer::Recycle (struct Buffer::Data *data)
95 {
96  NS_LOG_FUNCTION (data);
97  NS_ASSERT (data->m_count == 0);
98  NS_ASSERT (!IS_UNINITIALIZED (g_freeList));
99  g_maxSize = std::max (g_maxSize, data->m_size);
100  /* feed into free list */
101  if (data->m_size < g_maxSize ||
102  IS_DESTROYED (g_freeList) ||
103  g_freeList->size () > 1000)
104  {
105  Buffer::Deallocate (data);
106  }
107  else
108  {
109  NS_ASSERT (IS_INITIALIZED (g_freeList));
110  g_freeList->push_back (data);
111  }
112 }
113 
114 Buffer::Data *
115 Buffer::Create (uint32_t dataSize)
116 {
117  NS_LOG_FUNCTION (dataSize);
118  /* try to find a buffer correctly sized. */
119  if (IS_UNINITIALIZED (g_freeList))
120  {
121  g_freeList = new Buffer::FreeList ();
122  }
123  else if (IS_INITIALIZED (g_freeList))
124  {
125  while (!g_freeList->empty ())
126  {
127  struct Buffer::Data *data = g_freeList->back ();
128  g_freeList->pop_back ();
129  if (data->m_size >= dataSize)
130  {
131  data->m_count = 1;
132  return data;
133  }
134  Buffer::Deallocate (data);
135  }
136  }
137  struct Buffer::Data *data = Buffer::Allocate (dataSize);
138  NS_ASSERT (data->m_count == 1);
139  return data;
140 }
141 #else /* BUFFER_FREE_LIST */
142 void
144 {
145  NS_LOG_FUNCTION (data);
146  NS_ASSERT (data->m_count == 0);
147  Deallocate (data);
148 }
149 
150 Buffer::Data *
151 Buffer::Create (uint32_t size)
152 {
153  NS_LOG_FUNCTION (size);
154  return Allocate (size);
155 }
156 #endif /* BUFFER_FREE_LIST */
157 
158 struct Buffer::Data *
159 Buffer::Allocate (uint32_t reqSize)
160 {
161  NS_LOG_FUNCTION (reqSize);
162  if (reqSize == 0)
163  {
164  reqSize = 1;
165  }
166  NS_ASSERT (reqSize >= 1);
167  uint32_t size = reqSize - 1 + sizeof (struct Buffer::Data);
168  uint8_t *b = new uint8_t [size];
169  struct Buffer::Data *data = reinterpret_cast<struct Buffer::Data*>(b);
170  data->m_size = reqSize;
171  data->m_count = 1;
172  return data;
173 }
174 
175 void
177 {
178  NS_LOG_FUNCTION (data);
179  NS_ASSERT (data->m_count == 0);
180  uint8_t *buf = reinterpret_cast<uint8_t *> (data);
181  delete [] buf;
182 }
183 
185 {
186  NS_LOG_FUNCTION (this);
187  Initialize (0);
188 }
189 
190 Buffer::Buffer (uint32_t dataSize)
191 {
192  NS_LOG_FUNCTION (this << dataSize);
193  Initialize (dataSize);
194 }
195 
196 Buffer::Buffer (uint32_t dataSize, bool initialize)
197 {
198  NS_LOG_FUNCTION (this << dataSize << initialize);
199  if (initialize == true)
200  {
201  Initialize (dataSize);
202  }
203 }
204 
205 bool
207 {
208  NS_LOG_FUNCTION (this);
209 #if 0
210  // If you want to modify any code in this file, enable this checking code.
211  // Otherwise, there is not much point is enabling it because the
212  // current implementation has been fairly seriously tested and the cost
213  // of this constant checking is pretty high, even for a debug build.
214  bool offsetsOk =
217  m_zeroAreaEnd <= m_end;
218  bool dirtyOk =
220  m_end <= m_data->m_dirtyEnd;
221  bool internalSizeOk = m_end - (m_zeroAreaEnd - m_zeroAreaStart) <= m_data->m_size &&
222  m_start <= m_data->m_size &&
223  m_zeroAreaStart <= m_data->m_size;
224 
225  bool ok = m_data->m_count > 0 && offsetsOk && dirtyOk && internalSizeOk;
226  if (!ok)
227  {
228  LOG_INTERNAL_STATE ("check " << this <<
229  ", " << (offsetsOk ? "true" : "false") <<
230  ", " << (dirtyOk ? "true" : "false") <<
231  ", " << (internalSizeOk ? "true" : "false") << " ");
232  }
233  return ok;
234 #else
235  return true;
236 #endif
237 }
238 
239 void
240 Buffer::Initialize (uint32_t zeroSize)
241 {
242  NS_LOG_FUNCTION (this << zeroSize);
243  m_data = Buffer::Create (0);
244  m_start = std::min (m_data->m_size, g_recommendedStart);
247  m_zeroAreaEnd = m_zeroAreaStart + zeroSize;
252 }
253 
254 Buffer &
255 Buffer::operator = (Buffer const&o)
256 {
258  if (m_data != o.m_data)
259  {
260  // not assignment to self.
261  m_data->m_count--;
262  if (m_data->m_count == 0)
263  {
264  Recycle (m_data);
265  }
266  m_data = o.m_data;
267  m_data->m_count++;
268  }
273  m_start = o.m_start;
274  m_end = o.m_end;
276  return *this;
277 }
278 
280 {
281  NS_LOG_FUNCTION (this);
284  m_data->m_count--;
285  if (m_data->m_count == 0)
286  {
287  Recycle (m_data);
288  }
289 }
290 
291 uint32_t
293 {
294  NS_LOG_FUNCTION (this);
296 }
297 uint32_t
299 {
300  NS_LOG_FUNCTION (this);
301  return m_end - (m_zeroAreaEnd - m_zeroAreaStart);
302 }
303 
304 bool
306 {
307  NS_LOG_FUNCTION (this << start);
308  bool dirty;
310  bool isDirty = m_data->m_count > 1 && m_start > m_data->m_dirtyStart;
311  if (m_start >= start && !isDirty)
312  {
313  /* enough space in the buffer and not dirty.
314  * To add: |..|
315  * Before: |*****---------***|
316  * After: |***..---------***|
317  */
319  m_start -= start;
320  dirty = m_start > m_data->m_dirtyStart;
321  // update dirty area
323  }
324  else
325  {
326  uint32_t newSize = GetInternalSize () + start;
327  struct Buffer::Data *newData = Buffer::Create (newSize);
328  memcpy (newData->m_data + start, m_data->m_data + m_start, GetInternalSize ());
329  m_data->m_count--;
330  if (m_data->m_count == 0)
331  {
333  }
334  m_data = newData;
335 
336  int32_t delta = start - m_start;
337  m_start += delta;
338  m_zeroAreaStart += delta;
339  m_zeroAreaEnd += delta;
340  m_end += delta;
341  m_start -= start;
342 
343  // update dirty area
346 
347  dirty = true;
348 
349  }
351  LOG_INTERNAL_STATE ("add start=" << start << ", ");
353  return dirty;
354 }
355 bool
356 Buffer::AddAtEnd (uint32_t end)
357 {
358  NS_LOG_FUNCTION (this << end);
359  bool dirty;
361  bool isDirty = m_data->m_count > 1 && m_end < m_data->m_dirtyEnd;
362  if (GetInternalEnd () + end <= m_data->m_size && !isDirty)
363  {
364  /* enough space in buffer and not dirty
365  * Add: |...|
366  * Before: |**----*****|
367  * After: |**----...**|
368  */
370  m_end += end;
371  // update dirty area.
373 
374  dirty = m_end < m_data->m_dirtyEnd;
375 
376  }
377  else
378  {
379  uint32_t newSize = GetInternalSize () + end;
380  struct Buffer::Data *newData = Buffer::Create (newSize);
381  memcpy (newData->m_data, m_data->m_data + m_start, GetInternalSize ());
382  m_data->m_count--;
383  if (m_data->m_count == 0)
384  {
386  }
387  m_data = newData;
388 
389  int32_t delta = -m_start;
390  m_zeroAreaStart += delta;
391  m_zeroAreaEnd += delta;
392  m_end += delta;
393  m_start += delta;
394  m_end += end;
395 
396  // update dirty area
399 
400  dirty = true;
401 
402  }
404  LOG_INTERNAL_STATE ("add end=" << end << ", ");
406 
407  return dirty;
408 }
409 
410 void
411 Buffer::AddAtEnd (const Buffer &o)
412 {
413  NS_LOG_FUNCTION (this << &o);
414  if (m_data->m_count == 1 &&
415  m_end == m_zeroAreaEnd &&
416  m_end == m_data->m_dirtyEnd &&
417  o.m_start == o.m_zeroAreaStart &&
418  o.m_zeroAreaEnd - o.m_zeroAreaStart > 0)
419  {
425  uint32_t zeroSize = o.m_zeroAreaEnd - o.m_zeroAreaStart;
426  m_zeroAreaEnd += zeroSize;
429  uint32_t endData = o.m_end - o.m_zeroAreaEnd;
430  AddAtEnd (endData);
431  Buffer::Iterator dst = End ();
432  dst.Prev (endData);
433  Buffer::Iterator src = o.End ();
434  src.Prev (endData);
435  dst.Write (src, o.End ());
437  return;
438  }
439 
440  Buffer dst = CreateFullCopy ();
441  Buffer src = o.CreateFullCopy ();
442 
443  dst.AddAtEnd (src.GetSize ());
444  Buffer::Iterator destStart = dst.End ();
445  destStart.Prev (src.GetSize ());
446  destStart.Write (src.Begin (), src.End ());
447  *this = dst;
449 }
450 
451 void
453 {
454  NS_LOG_FUNCTION (this << start);
456  uint32_t newStart = m_start + start;
457  if (newStart <= m_zeroAreaStart)
458  {
459  /* only remove start of buffer
460  */
461  m_start = newStart;
462  }
463  else if (newStart <= m_zeroAreaEnd)
464  {
465  /* remove start of buffer _and_ start of zero area
466  */
467  uint32_t delta = newStart - m_zeroAreaStart;
469  m_zeroAreaEnd -= delta;
470  m_end -= delta;
471  }
472  else if (newStart <= m_end)
473  {
474  /* remove start of buffer, complete zero area, and part
475  * of end of buffer
476  */
477  NS_ASSERT (m_end >= start);
478  uint32_t zeroSize = m_zeroAreaEnd - m_zeroAreaStart;
479  m_start = newStart - zeroSize;
480  m_end -= zeroSize;
481  m_zeroAreaStart = m_start;
483  }
484  else
485  {
486  /* remove all buffer */
488  m_start = m_end;
490  m_zeroAreaStart = m_end;
491  }
493  LOG_INTERNAL_STATE ("rem start=" << start << ", ");
495 }
496 void
497 Buffer::RemoveAtEnd (uint32_t end)
498 {
499  NS_LOG_FUNCTION (this << end);
501  uint32_t newEnd = m_end - std::min (end, m_end - m_start);
502  if (newEnd > m_zeroAreaEnd)
503  {
504  /* remove part of end of buffer */
505  m_end = newEnd;
506  }
507  else if (newEnd > m_zeroAreaStart)
508  {
509  /* remove end of buffer, part of zero area */
510  m_end = newEnd;
511  m_zeroAreaEnd = newEnd;
512  }
513  else if (newEnd > m_start)
514  {
515  /* remove end of buffer, zero area, part of start of buffer */
516  m_end = newEnd;
517  m_zeroAreaEnd = newEnd;
518  m_zeroAreaStart = newEnd;
519  }
520  else
521  {
522  /* remove all buffer */
523  m_end = m_start;
526  }
528  LOG_INTERNAL_STATE ("rem end=" << end << ", ");
530 }
531 
532 Buffer
533 Buffer::CreateFragment (uint32_t start, uint32_t length) const
534 {
535  NS_LOG_FUNCTION (this << start << length);
537  Buffer tmp = *this;
538  tmp.RemoveAtStart (start);
539  tmp.RemoveAtEnd (GetSize () - (start + length));
541  return tmp;
542 }
543 
544 Buffer
546 {
547  NS_LOG_FUNCTION (this);
549  if (m_zeroAreaEnd - m_zeroAreaStart != 0)
550  {
551  Buffer tmp;
554  uint32_t dataStart = m_zeroAreaStart - m_start;
555  tmp.AddAtStart (dataStart);
556  tmp.Begin ().Write (m_data->m_data+m_start, dataStart);
557  uint32_t dataEnd = m_end - m_zeroAreaEnd;
558  tmp.AddAtEnd (dataEnd);
559  Buffer::Iterator i = tmp.End ();
560  i.Prev (dataEnd);
561  i.Write (m_data->m_data+m_zeroAreaStart,dataEnd);
562  NS_ASSERT (tmp.CheckInternalState ());
563  return tmp;
564  }
566  return *this;
567 }
568 
569 uint32_t
571 {
572  NS_LOG_FUNCTION (this);
573  uint32_t dataStart = (m_zeroAreaStart - m_start + 3) & (~0x3);
574  uint32_t dataEnd = (m_end - m_zeroAreaEnd + 3) & (~0x3);
575 
576  // total size 4-bytes for dataStart length
577  // + X number of bytes for dataStart
578  // + 4-bytes for dataEnd length
579  // + X number of bytes for dataEnd
580  uint32_t sz = sizeof (uint32_t)
581  + sizeof (uint32_t)
582  + dataStart
583  + sizeof (uint32_t)
584  + dataEnd;
585 
586  return sz;
587 }
588 
589 uint32_t
590 Buffer::Serialize (uint8_t* buffer, uint32_t maxSize) const
591 {
592  NS_LOG_FUNCTION (this << &buffer << maxSize);
593  uint32_t* p = reinterpret_cast<uint32_t *> (buffer);
594  uint32_t size = 0;
595 
596  // Add the zero data length
597  if (size + 4 <= maxSize)
598  {
599  size += 4;
601  }
602  else
603  {
604  return 0;
605  }
606 
607  // Add the length of actual start data
608  uint32_t dataStartLength = m_zeroAreaStart - m_start;
609  if (size + 4 <= maxSize)
610  {
611  size += 4;
612  *p++ = dataStartLength;
613  }
614  else
615  {
616  return 0;
617  }
618 
619  // Add the actual data
620  if (size + ((dataStartLength + 3) & (~3)) <= maxSize)
621  {
622  size += (dataStartLength + 3) & (~3);
623  memcpy (p, m_data->m_data + m_start, dataStartLength);
624  p += (((dataStartLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
625  }
626  else
627  {
628  return 0;
629  }
630 
631  // Add the length of the actual end data
632  uint32_t dataEndLength = m_end - m_zeroAreaEnd;
633  if (size + 4 <= maxSize)
634  {
635  size += 4;
636  *p++ = dataEndLength;
637  }
638  else
639  {
640  return 0;
641  }
642 
643  // Add the actual data
644  if (size + ((dataEndLength + 3) & (~3)) <= maxSize)
645  {
646  size += (dataEndLength + 3) & (~3);
647  memcpy (p, m_data->m_data+m_zeroAreaStart,dataEndLength);
648  p += (((dataEndLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
649  }
650  else
651  {
652  return 0;
653  }
654 
655  // Serialzed everything successfully
656  return 1;
657 }
658 
659 uint32_t
660 Buffer::Deserialize (const uint8_t *buffer, uint32_t size)
661 {
662  NS_LOG_FUNCTION (this << &buffer << size);
663  const uint32_t* p = reinterpret_cast<const uint32_t *> (buffer);
664  uint32_t sizeCheck = size-4;
665 
666  NS_ASSERT (sizeCheck >= 4);
667  uint32_t zeroDataLength = *p++;
668  sizeCheck -= 4;
669 
670  // Create zero bytes
671  Initialize (zeroDataLength);
672 
673  // Add start data
674  NS_ASSERT (sizeCheck >= 4);
675  uint32_t dataStartLength = *p++;
676  sizeCheck -= 4;
677  AddAtStart (dataStartLength);
678 
679  NS_ASSERT (sizeCheck >= dataStartLength);
680  Begin ().Write (reinterpret_cast<uint8_t *> (const_cast<uint32_t *> (p)), dataStartLength);
681  p += (((dataStartLength+3)&(~3))/4); // Advance p, insuring 4 byte boundary
682  sizeCheck -= ((dataStartLength+3)&(~3));
683 
684  // Add end data
685  NS_ASSERT (sizeCheck >= 4);
686  uint32_t dataEndLength = *p++;
687  sizeCheck -= 4;
688  AddAtEnd (dataEndLength);
689 
690  NS_ASSERT (sizeCheck >= dataEndLength);
691  Buffer::Iterator tmp = End ();
692  tmp.Prev (dataEndLength);
693  tmp.Write (reinterpret_cast<uint8_t *> (const_cast<uint32_t *> (p)), dataEndLength);
694  p += (((dataEndLength+3)&(~3))/4); // Advance p, insuring 4 byte boundary
695  sizeCheck -= ((dataEndLength+3)&(~3));
696 
697  NS_ASSERT (sizeCheck == 0);
698  // return zero if buffer did not
699  // contain a complete message
700  return (sizeCheck != 0) ? 0 : 1;
701 }
702 
703 int32_t
705 {
706  NS_LOG_FUNCTION (this);
707  return m_start;
708 }
709 int32_t
711 {
712  NS_LOG_FUNCTION (this);
713  return m_end;
714 }
715 
716 
717 void
719 {
720  NS_LOG_FUNCTION (this);
722  Buffer tmp = CreateFullCopy ();
723  *const_cast<Buffer *> (this) = tmp;
725 }
726 
727 
728 uint8_t const*
729 Buffer::PeekData (void) const
730 {
731  NS_LOG_FUNCTION (this);
735  return m_data->m_data + m_start;
736 }
737 
738 void
739 Buffer::CopyData (std::ostream *os, uint32_t size) const
740 {
741  NS_LOG_FUNCTION (this << &os << size);
742  if (size > 0)
743  {
744  uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size);
745  os->write ((const char*)(m_data->m_data + m_start), tmpsize);
746  if (size > tmpsize)
747  {
748  size -= m_zeroAreaStart-m_start;
749  tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size);
750  uint32_t left = tmpsize;
751  while (left > 0)
752  {
753  uint32_t toWrite = std::min (left, g_zeroes.size);
754  os->write (g_zeroes.buffer, toWrite);
755  left -= toWrite;
756  }
757  if (size > tmpsize)
758  {
759  size -= tmpsize;
760  tmpsize = std::min (m_end - m_zeroAreaEnd, size);
761  os->write ((const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
762  }
763  }
764  }
765 }
766 
767 uint32_t
768 Buffer::CopyData (uint8_t *buffer, uint32_t size) const
769 {
770  NS_LOG_FUNCTION (this << &buffer << size);
771  uint32_t originalSize = size;
772  if (size > 0)
773  {
774  uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size);
775  memcpy (buffer, (const char*)(m_data->m_data + m_start), tmpsize);
776  buffer += tmpsize;
777  size -= tmpsize;
778  if (size > 0)
779  {
780  tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size);
781  uint32_t left = tmpsize;
782  while (left > 0)
783  {
784  uint32_t toWrite = std::min (left, g_zeroes.size);
785  memcpy (buffer, g_zeroes.buffer, toWrite);
786  left -= toWrite;
787  buffer += toWrite;
788  }
789  size -= tmpsize;
790  if (size > 0)
791  {
792  tmpsize = std::min (m_end - m_zeroAreaEnd, size);
793  memcpy (buffer, (const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
794  size -= tmpsize;
795  }
796  }
797  }
798  return originalSize - size;
799 }
800 
801 /******************************************************
802  * The buffer iterator below.
803  ******************************************************/
804 
805 
806 uint32_t
808 {
809  NS_LOG_FUNCTION (this << &o);
810  NS_ASSERT (m_data == o.m_data);
811  int32_t diff = m_current - o.m_current;
812  if (diff < 0)
813  {
814  return -diff;
815  }
816  else
817  {
818  return diff;
819  }
820 }
821 
822 bool
824 {
825  NS_LOG_FUNCTION (this);
826  return m_current == m_dataEnd;
827 }
828 bool
830 {
831  NS_LOG_FUNCTION (this);
832  return m_current == m_dataStart;
833 }
834 
835 bool
836 Buffer::Iterator::CheckNoZero (uint32_t start, uint32_t end) const
837 {
838  NS_LOG_FUNCTION (this << &start << &end);
839  bool ok = true;
840  for (uint32_t i = start; i < end; i++)
841  {
842  if (!Check (i))
843  {
844  ok = false;
845  }
846  }
847  return ok;
848 }
849 bool
850 Buffer::Iterator::Check (uint32_t i) const
851 {
852  NS_LOG_FUNCTION (this << &i);
853  return i >= m_dataStart &&
854  !(i >= m_zeroStart && i < m_zeroEnd) &&
855  i <= m_dataEnd;
856 }
857 
858 
859 void
861 {
862  NS_LOG_FUNCTION (this << &start << &end);
863  NS_ASSERT (start.m_data == end.m_data);
864  NS_ASSERT (start.m_current <= end.m_current);
865  NS_ASSERT (start.m_zeroStart == end.m_zeroStart);
866  NS_ASSERT (start.m_zeroEnd == end.m_zeroEnd);
867  NS_ASSERT (m_data != start.m_data);
868  uint32_t size = end.m_current - start.m_current;
869  NS_ASSERT_MSG (CheckNoZero (m_current, m_current + size),
870  GetWriteErrorMessage ());
871  if (start.m_current <= start.m_zeroStart)
872  {
873  uint32_t toCopy = std::min (size, start.m_zeroStart - start.m_current);
874  memcpy (&m_data[m_current], &start.m_data[start.m_current], toCopy);
875  start.m_current += toCopy;
876  m_current += toCopy;
877  size -= toCopy;
878  }
879  if (start.m_current <= start.m_zeroEnd)
880  {
881  uint32_t toCopy = std::min (size, start.m_zeroEnd - start.m_current);
882  memset (&m_data[m_current], 0, toCopy);
883  start.m_current += toCopy;
884  m_current += toCopy;
885  size -= toCopy;
886  }
887  uint32_t toCopy = std::min (size, start.m_dataEnd - start.m_current);
888  uint8_t *from = &start.m_data[start.m_current - (start.m_zeroEnd-start.m_zeroStart)];
889  uint8_t *to = &m_data[m_current];
890  memcpy (to, from, toCopy);
891  m_current += toCopy;
892 }
893 
894 void
896 {
897  NS_LOG_FUNCTION (this << data);
898  WriteU8 (data & 0xff);
899  data >>= 8;
900  WriteU8 (data & 0xff);
901 }
902 void
904 {
905  NS_LOG_FUNCTION (this << data);
906  WriteU8 (data & 0xff);
907  data >>= 8;
908  WriteU8 (data & 0xff);
909  data >>= 8;
910  WriteU8 (data & 0xff);
911  data >>= 8;
912  WriteU8 (data & 0xff);
913 }
914 void
916 {
917  NS_LOG_FUNCTION (this << data);
918  WriteU8 (data & 0xff);
919  data >>= 8;
920  WriteU8 (data & 0xff);
921  data >>= 8;
922  WriteU8 (data & 0xff);
923  data >>= 8;
924  WriteU8 (data & 0xff);
925  data >>= 8;
926  WriteU8 (data & 0xff);
927  data >>= 8;
928  WriteU8 (data & 0xff);
929  data >>= 8;
930  WriteU8 (data & 0xff);
931  data >>= 8;
932  WriteU8 (data & 0xff);
933 }
934 void
936 {
937  NS_LOG_FUNCTION (this << data);
938  WriteU8 ((data >> 0) & 0xff);
939  WriteU8 ((data >> 8) & 0xff);
940 }
941 void
943 {
944  NS_LOG_FUNCTION (this << data);
945  WriteU8 ((data >> 0) & 0xff);
946  WriteU8 ((data >> 8) & 0xff);
947  WriteU8 ((data >> 16) & 0xff);
948  WriteU8 ((data >> 24) & 0xff);
949 }
950 void
952 {
953  NS_LOG_FUNCTION (this << data);
954  WriteU8 ((data >> 0) & 0xff);
955  WriteU8 ((data >> 8) & 0xff);
956  WriteU8 ((data >> 16) & 0xff);
957  WriteU8 ((data >> 24) & 0xff);
958  WriteU8 ((data >> 32) & 0xff);
959  WriteU8 ((data >> 40) & 0xff);
960  WriteU8 ((data >> 48) & 0xff);
961  WriteU8 ((data >> 56) & 0xff);
962 }
963 
964 void
966 {
967  NS_LOG_FUNCTION (this << data);
968  WriteU8 ((data >> 56) & 0xff);
969  WriteU8 ((data >> 48) & 0xff);
970  WriteU8 ((data >> 40) & 0xff);
971  WriteU8 ((data >> 32) & 0xff);
972  WriteU8 ((data >> 24) & 0xff);
973  WriteU8 ((data >> 16) & 0xff);
974  WriteU8 ((data >> 8) & 0xff);
975  WriteU8 ((data >> 0) & 0xff);
976 }
977 void
978 Buffer::Iterator::Write (uint8_t const*buffer, uint32_t size)
979 {
980  NS_LOG_FUNCTION (this << &buffer << size);
981  NS_ASSERT_MSG (CheckNoZero (m_current, size),
982  GetWriteErrorMessage ());
983  uint8_t *to;
984  if (m_current <= m_zeroStart)
985  {
986  to = &m_data[m_current];
987  }
988  else
989  {
990  to = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
991  }
992  memcpy (to, buffer, size);
993  m_current += size;
994 }
995 
996 uint32_t
998 {
999  NS_LOG_FUNCTION (this);
1000  uint8_t byte0 = ReadU8 ();
1001  uint8_t byte1 = ReadU8 ();
1002  uint8_t byte2 = ReadU8 ();
1003  uint8_t byte3 = ReadU8 ();
1004  uint32_t data = byte3;
1005  data <<= 8;
1006  data |= byte2;
1007  data <<= 8;
1008  data |= byte1;
1009  data <<= 8;
1010  data |= byte0;
1011  return data;
1012 }
1013 uint64_t
1015 {
1016  NS_LOG_FUNCTION (this);
1017  uint8_t byte0 = ReadU8 ();
1018  uint8_t byte1 = ReadU8 ();
1019  uint8_t byte2 = ReadU8 ();
1020  uint8_t byte3 = ReadU8 ();
1021  uint8_t byte4 = ReadU8 ();
1022  uint8_t byte5 = ReadU8 ();
1023  uint8_t byte6 = ReadU8 ();
1024  uint8_t byte7 = ReadU8 ();
1025  uint64_t data = byte7;
1026  data <<= 8;
1027  data |= byte6;
1028  data <<= 8;
1029  data |= byte5;
1030  data <<= 8;
1031  data |= byte4;
1032  data <<= 8;
1033  data |= byte3;
1034  data <<= 8;
1035  data |= byte2;
1036  data <<= 8;
1037  data |= byte1;
1038  data <<= 8;
1039  data |= byte0;
1040 
1041  return data;
1042 }
1043 uint16_t
1045 {
1046  NS_LOG_FUNCTION (this);
1047  uint16_t retval = 0;
1048  retval |= ReadU8 ();
1049  retval <<= 8;
1050  retval |= ReadU8 ();
1051  return retval;
1052 }
1053 uint32_t
1055 {
1056  NS_LOG_FUNCTION (this);
1057  uint32_t retval = 0;
1058  retval |= ReadU8 ();
1059  retval <<= 8;
1060  retval |= ReadU8 ();
1061  retval <<= 8;
1062  retval |= ReadU8 ();
1063  retval <<= 8;
1064  retval |= ReadU8 ();
1065  return retval;
1066 }
1067 uint64_t
1069 {
1070  NS_LOG_FUNCTION (this);
1071  uint64_t retval = 0;
1072  retval |= ReadU8 ();
1073  retval <<= 8;
1074  retval |= ReadU8 ();
1075  retval <<= 8;
1076  retval |= ReadU8 ();
1077  retval <<= 8;
1078  retval |= ReadU8 ();
1079  retval <<= 8;
1080  retval |= ReadU8 ();
1081  retval <<= 8;
1082  retval |= ReadU8 ();
1083  retval <<= 8;
1084  retval |= ReadU8 ();
1085  retval <<= 8;
1086  retval |= ReadU8 ();
1087  return retval;
1088 }
1089 uint16_t
1091 {
1092  NS_LOG_FUNCTION (this);
1093  uint8_t byte0 = ReadU8 ();
1094  uint8_t byte1 = ReadU8 ();
1095  uint16_t data = byte1;
1096  data <<= 8;
1097  data |= byte0;
1098  return data;
1099 }
1100 uint32_t
1102 {
1103  NS_LOG_FUNCTION (this);
1104  uint8_t byte0 = ReadU8 ();
1105  uint8_t byte1 = ReadU8 ();
1106  uint8_t byte2 = ReadU8 ();
1107  uint8_t byte3 = ReadU8 ();
1108  uint32_t data = byte3;
1109  data <<= 8;
1110  data |= byte2;
1111  data <<= 8;
1112  data |= byte1;
1113  data <<= 8;
1114  data |= byte0;
1115  return data;
1116 }
1117 uint64_t
1119 {
1120  NS_LOG_FUNCTION (this);
1121  uint8_t byte0 = ReadU8 ();
1122  uint8_t byte1 = ReadU8 ();
1123  uint8_t byte2 = ReadU8 ();
1124  uint8_t byte3 = ReadU8 ();
1125  uint8_t byte4 = ReadU8 ();
1126  uint8_t byte5 = ReadU8 ();
1127  uint8_t byte6 = ReadU8 ();
1128  uint8_t byte7 = ReadU8 ();
1129  uint64_t data = byte7;
1130  data <<= 8;
1131  data |= byte6;
1132  data <<= 8;
1133  data |= byte5;
1134  data <<= 8;
1135  data |= byte4;
1136  data <<= 8;
1137  data |= byte3;
1138  data <<= 8;
1139  data |= byte2;
1140  data <<= 8;
1141  data |= byte1;
1142  data <<= 8;
1143  data |= byte0;
1144 
1145  return data;
1146 }
1147 void
1148 Buffer::Iterator::Read (uint8_t *buffer, uint32_t size)
1149 {
1150  NS_LOG_FUNCTION (this << &buffer << size);
1151  for (uint32_t i = 0; i < size; i++)
1152  {
1153  buffer[i] = ReadU8 ();
1154  }
1155 }
1156 
1157 uint16_t
1159 {
1160  NS_LOG_FUNCTION (this << size);
1161  return CalculateIpChecksum (size, 0);
1162 }
1163 
1164 uint16_t
1165 Buffer::Iterator::CalculateIpChecksum (uint16_t size, uint32_t initialChecksum)
1166 {
1167  NS_LOG_FUNCTION (this << size << initialChecksum);
1168  /* see RFC 1071 to understand this code. */
1169  uint32_t sum = initialChecksum;
1170 
1171  for (int j = 0; j < size/2; j++)
1172  sum += ReadU16 ();
1173 
1174  if (size & 1)
1175  sum += ReadU8 ();
1176 
1177  while (sum >> 16)
1178  sum = (sum & 0xffff) + (sum >> 16);
1179  return ~sum;
1180 }
1181 
1182 uint32_t
1184 {
1185  NS_LOG_FUNCTION (this);
1186  return m_dataEnd - m_dataStart;
1187 }
1188 
1189 
1190 std::string
1192 {
1193  NS_LOG_FUNCTION (this);
1194  std::string str = "You have attempted to read beyond the bounds of the "
1195  "available buffer space. This usually indicates that a "
1196  "Header::Deserialize or Trailer::Deserialize method "
1197  "is trying to read data which was not written by "
1198  "a Header::Serialize or Trailer::Serialize method. "
1199  "In short: check the code of your Serialize and Deserialize "
1200  "methods.";
1201  return str;
1202 }
1203 std::string
1205 {
1206  NS_LOG_FUNCTION (this);
1207  std::string str;
1208  if (m_current < m_dataStart)
1209  {
1210  str = "You have attempted to write before the start of the available "
1211  "buffer space. This usually indicates that Trailer::GetSerializedSize "
1212  "returned a size which is too small compared to what Trailer::Serialize "
1213  "is actually using.";
1214  }
1215  else if (m_current >= m_dataEnd)
1216  {
1217  str = "You have attempted to write after the end of the available "
1218  "buffer space. This usually indicates that Header::GetSerializedSize "
1219  "returned a size which is too small compared to what Header::Serialize "
1220  "is actually using.";
1221  }
1222  else
1223  {
1224  NS_ASSERT (m_current >= m_zeroStart && m_current < m_zeroEnd);
1225  str = "You have attempted to write inside the payload area of the "
1226  "buffer. This usually indicates that your Serialize method uses more "
1227  "buffer space than what your GetSerialized method returned.";
1228  }
1229  return str;
1230 }
1231 
1232 
1233 } // namespace ns3
1234 
1235 
uint16_t CalculateIpChecksum(uint16_t size)
Calculate the checksum.
Definition: buffer.cc:1158
uint16_t SlowReadNtohU16(void)
Definition: buffer.cc:1044
void Initialize(uint32_t zeroSize)
Definition: buffer.cc:240
void WriteHtonU64(uint64_t data)
Definition: buffer.cc:965
uint32_t m_end
Definition: buffer.h:614
uint32_t ReadU32(void)
Definition: buffer.cc:997
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:345
void RemoveAtEnd(uint32_t end)
Definition: buffer.cc:497
bool IsStart(void) const
Definition: buffer.cc:829
uint8_t * m_data
Definition: buffer.h:397
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:452
uint32_t m_size
Definition: buffer.h:555
static struct anonymous_namespace{buffer.cc}::Zeroes g_zeroes
uint64_t ReadNtohU64(void)
Definition: buffer.cc:1068
uint32_t m_count
Definition: buffer.h:552
#define NS_ASSERT(condition)
Definition: assert.h:64
uint32_t GetSerializedSize(void) const
Definition: buffer.cc:570
bool CheckInternalState(void) const
Definition: buffer.cc:206
Buffer & operator=(Buffer const &o)
Definition: buffer.cc:255
uint32_t m_start
Definition: buffer.h:610
uint32_t GetDistanceFrom(Iterator const &o) const
Definition: buffer.cc:807
iterator in a Buffer instance
Definition: buffer.h:98
uint32_t SlowReadNtohU32(void)
Definition: buffer.cc:1054
uint32_t m_zeroStart
Definition: buffer.h:377
uint32_t m_dirtyEnd
Definition: buffer.h:563
uint32_t Deserialize(const uint8_t *buffer, uint32_t size)
Definition: buffer.cc:660
bool IsEnd(void) const
Definition: buffer.cc:823
uint8_t m_data[1]
Definition: buffer.h:567
This data structure is variable-sized through its last member whose size is determined at allocation ...
Definition: buffer.h:547
std::string GetWriteErrorMessage(void) const
Definition: buffer.cc:1204
void Prev(void)
go backward by one byte
Definition: buffer.h:672
uint8_t data[writeSize]
void WriteU16(uint16_t data)
Definition: buffer.cc:895
static struct Buffer::Data * Create(uint32_t size)
Definition: buffer.cc:151
Buffer::Iterator End(void) const
Definition: buffer.h:881
uint8_t const * PeekData(void) const
Definition: buffer.cc:729
NS_LOG_COMPONENT_DEFINE("Buffer")
uint32_t m_current
Definition: buffer.h:393
void WriteU64(uint64_t data)
Definition: buffer.cc:915
void CopyData(std::ostream *os, uint32_t size) const
Copy the specified amount of data from the buffer to the given output stream.
Definition: buffer.cc:739
int32_t GetCurrentEndOffset(void) const
Definition: buffer.cc:710
void TransformIntoRealBuffer(void) const
Definition: buffer.cc:718
Buffer::Iterator Begin(void) const
Definition: buffer.h:875
bool Check(uint32_t i) const
Definition: buffer.cc:850
bool CheckNoZero(uint32_t start, uint32_t end) const
Definition: buffer.cc:836
std::string GetReadErrorMessage(void) const
Definition: buffer.cc:1191
static void Recycle(struct Buffer::Data *data)
Definition: buffer.cc:143
uint32_t m_dataEnd
Definition: buffer.h:389
void Read(uint8_t *buffer, uint32_t size)
Definition: buffer.cc:1148
uint32_t m_zeroEnd
Definition: buffer.h:381
uint32_t m_zeroAreaStart
Definition: buffer.h:602
uint64_t ReadU64(void)
Definition: buffer.cc:1014
uint32_t GetSize(void) const
Definition: buffer.h:869
Buffer CreateFragment(uint32_t start, uint32_t length) const
Definition: buffer.cc:533
bool AddAtEnd(uint32_t end)
Definition: buffer.cc:356
void WriteHtolsbU16(uint16_t data)
Definition: buffer.cc:935
static struct Buffer::Data * Allocate(uint32_t reqSize)
Definition: buffer.cc:159
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
uint32_t Serialize(uint8_t *buffer, uint32_t maxSize) const
Definition: buffer.cc:590
struct Data * m_data
Definition: buffer.h:580
uint32_t m_dirtyStart
Definition: buffer.h:559
void WriteU8(uint8_t data)
Definition: buffer.h:690
ns3::ByteTagListDataFreeList g_freeList
uint32_t m_maxZeroAreaStart
Definition: buffer.h:591
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:951
Buffer CreateFullCopy(void) const
Definition: buffer.cc:545
#define LOG_INTERNAL_STATE(y)
Definition: buffer.cc:26
static void Deallocate(struct Buffer::Data *data)
Definition: buffer.cc:176
static uint32_t g_recommendedStart
location in a newly-allocated buffer where you should start writing data.
Definition: buffer.h:597
void Write(uint8_t const *buffer, uint32_t size)
Definition: buffer.cc:978
uint32_t GetInternalSize(void) const
Definition: buffer.cc:292
uint16_t ReadLsbtohU16(void)
Definition: buffer.cc:1090
bool AddAtStart(uint32_t start)
Definition: buffer.cc:305
int32_t GetCurrentStartOffset(void) const
Definition: buffer.cc:704
uint64_t ReadLsbtohU64(void)
Definition: buffer.cc:1118
void WriteU32(uint32_t data)
Definition: buffer.cc:903
uint32_t GetInternalEnd(void) const
Definition: buffer.cc:298
uint32_t GetSize(void) const
Definition: buffer.cc:1183
static uint32_t g_maxSize
uint32_t ReadLsbtohU32(void)
Definition: buffer.cc:1101
uint32_t m_zeroAreaEnd
Definition: buffer.h:606
void WriteHtolsbU32(uint32_t data)
Definition: buffer.cc:942