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