A Discrete-Event Network Simulator
API
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 #define LOG_INTERNAL_STATE(y) \
25  NS_LOG_LOGIC (y << "start="<<m_start<<", end="<<m_end<<", zero start="<<m_zeroAreaStart<< \
26  ", zero end="<<m_zeroAreaEnd<<", count="<<m_data->m_count<<", size="<<m_data->m_size<< \
27  ", dirty start="<<m_data->m_dirtyStart<<", dirty end="<<m_data->m_dirtyEnd)
28 
29 namespace {
30 
35 static struct Zeroes
36 {
37  Zeroes ()
38  : size (1000)
39  {
40  memset (buffer, 0, size);
41  }
42  char buffer[1000];
43  const uint32_t size;
45 
46 }
47 
48 namespace ns3 {
49 
50 NS_LOG_COMPONENT_DEFINE ("Buffer");
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 {
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  {
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  }
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 {
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 {
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);
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 void
310 {
311  NS_LOG_FUNCTION (this << start);
313  bool isDirty = m_data->m_count > 1 && m_start > m_data->m_dirtyStart;
314  if (m_start >= start && !isDirty)
315  {
316  /* enough space in the buffer and not dirty.
317  * To add: |..|
318  * Before: |*****---------***|
319  * After: |***..---------***|
320  */
322  m_start -= start;
323  // update dirty area
325  }
326  else
327  {
328  uint32_t newSize = GetInternalSize () + start;
329  struct Buffer::Data *newData = Buffer::Create (newSize);
330  memcpy (newData->m_data + start, m_data->m_data + m_start, GetInternalSize ());
331  m_data->m_count--;
332  if (m_data->m_count == 0)
333  {
335  }
336  m_data = newData;
337 
338  int32_t delta = start - m_start;
339  m_start += delta;
340  m_zeroAreaStart += delta;
341  m_zeroAreaEnd += delta;
342  m_end += delta;
343  m_start -= start;
344 
345  // update dirty area
348  }
350  LOG_INTERNAL_STATE ("add start=" << start << ", ");
352 }
353 void
354 Buffer::AddAtEnd (uint32_t end)
355 {
356  NS_LOG_FUNCTION (this << end);
358  bool isDirty = m_data->m_count > 1 && m_end < m_data->m_dirtyEnd;
359  if (GetInternalEnd () + end <= m_data->m_size && !isDirty)
360  {
361  /* enough space in buffer and not dirty
362  * Add: |...|
363  * Before: |**----*****|
364  * After: |**----...**|
365  */
367  m_end += end;
368  // update dirty area.
370  }
371  else
372  {
373  uint32_t newSize = GetInternalSize () + end;
374  struct Buffer::Data *newData = Buffer::Create (newSize);
375  memcpy (newData->m_data, m_data->m_data + m_start, GetInternalSize ());
376  m_data->m_count--;
377  if (m_data->m_count == 0)
378  {
380  }
381  m_data = newData;
382 
383  int32_t delta = -m_start;
384  m_zeroAreaStart += delta;
385  m_zeroAreaEnd += delta;
386  m_end += delta;
387  m_start += delta;
388  m_end += end;
389 
390  // update dirty area
393  }
395  LOG_INTERNAL_STATE ("add end=" << end << ", ");
397 }
398 
399 void
401 {
402  NS_LOG_FUNCTION (this << &o);
403 
404  if (m_data->m_count == 1 &&
406  m_end == m_data->m_dirtyEnd &&
407  o.m_start == o.m_zeroAreaStart &&
408  o.m_zeroAreaEnd - o.m_zeroAreaStart > 0)
409  {
416  {
418  }
419  uint32_t zeroSize = o.m_zeroAreaEnd - o.m_zeroAreaStart;
420  m_zeroAreaEnd = m_end + zeroSize;
423  uint32_t endData = o.m_end - o.m_zeroAreaEnd;
424  AddAtEnd (endData);
425  Buffer::Iterator dst = End ();
426  dst.Prev (endData);
427  Buffer::Iterator src = o.End ();
428  src.Prev (endData);
429  dst.Write (src, o.End ());
431  return;
432  }
433 
434  *this = CreateFullCopy ();
435  AddAtEnd (o.GetSize ());
436  Buffer::Iterator destStart = End ();
437  destStart.Prev (o.GetSize ());
438  destStart.Write (o.Begin (), o.End ());
440 }
441 
442 void
444 {
445  NS_LOG_FUNCTION (this << start);
447  uint32_t newStart = m_start + start;
448  if (newStart <= m_zeroAreaStart)
449  {
450  /* only remove start of buffer
451  */
452  m_start = newStart;
453  }
454  else if (newStart <= m_zeroAreaEnd)
455  {
456  /* remove start of buffer _and_ start of zero area
457  */
458  uint32_t delta = newStart - m_zeroAreaStart;
460  m_zeroAreaEnd -= delta;
461  m_end -= delta;
462  }
463  else if (newStart <= m_end)
464  {
465  /* remove start of buffer, complete zero area, and part
466  * of end of buffer
467  */
468  NS_ASSERT (m_end >= start);
469  uint32_t zeroSize = m_zeroAreaEnd - m_zeroAreaStart;
470  m_start = newStart - zeroSize;
471  m_end -= zeroSize;
474  }
475  else
476  {
477  /* remove all buffer */
479  m_start = m_end;
482  }
484  LOG_INTERNAL_STATE ("rem start=" << start << ", ");
486 }
487 void
488 Buffer::RemoveAtEnd (uint32_t end)
489 {
490  NS_LOG_FUNCTION (this << end);
492  uint32_t newEnd = m_end - std::min (end, m_end - m_start);
493  if (newEnd > m_zeroAreaEnd)
494  {
495  /* remove part of end of buffer */
496  m_end = newEnd;
497  }
498  else if (newEnd > m_zeroAreaStart)
499  {
500  /* remove end of buffer, part of zero area */
501  m_end = newEnd;
502  m_zeroAreaEnd = newEnd;
503  }
504  else if (newEnd > m_start)
505  {
506  /* remove end of buffer, zero area, part of start of buffer */
507  m_end = newEnd;
508  m_zeroAreaEnd = newEnd;
509  m_zeroAreaStart = newEnd;
510  }
511  else
512  {
513  /* remove all buffer */
514  m_end = m_start;
517  }
519  LOG_INTERNAL_STATE ("rem end=" << end << ", ");
521 }
522 
523 Buffer
524 Buffer::CreateFragment (uint32_t start, uint32_t length) const
525 {
526  NS_LOG_FUNCTION (this << start << length);
528  Buffer tmp = *this;
529  tmp.RemoveAtStart (start);
530  tmp.RemoveAtEnd (GetSize () - (start + length));
532  return tmp;
533 }
534 
535 Buffer
537 {
538  NS_LOG_FUNCTION (this);
540  if (m_zeroAreaEnd - m_zeroAreaStart != 0)
541  {
542  Buffer tmp;
545  uint32_t dataStart = m_zeroAreaStart - m_start;
546  tmp.AddAtStart (dataStart);
547  tmp.Begin ().Write (m_data->m_data+m_start, dataStart);
548  uint32_t dataEnd = m_end - m_zeroAreaEnd;
549  tmp.AddAtEnd (dataEnd);
550  Buffer::Iterator i = tmp.End ();
551  i.Prev (dataEnd);
552  i.Write (m_data->m_data+m_zeroAreaStart,dataEnd);
553  NS_ASSERT (tmp.CheckInternalState ());
554  return tmp;
555  }
557  return *this;
558 }
559 
560 uint32_t
562 {
563  NS_LOG_FUNCTION (this);
564  uint32_t dataStart = (m_zeroAreaStart - m_start + 3) & (~0x3);
565  uint32_t dataEnd = (m_end - m_zeroAreaEnd + 3) & (~0x3);
566 
567  // total size 4-bytes for dataStart length
568  // + X number of bytes for dataStart
569  // + 4-bytes for dataEnd length
570  // + X number of bytes for dataEnd
571  uint32_t sz = sizeof (uint32_t)
572  + sizeof (uint32_t)
573  + dataStart
574  + sizeof (uint32_t)
575  + dataEnd;
576 
577  return sz;
578 }
579 
580 uint32_t
581 Buffer::Serialize (uint8_t* buffer, uint32_t maxSize) const
582 {
583  NS_LOG_FUNCTION (this << &buffer << maxSize);
584  uint32_t* p = reinterpret_cast<uint32_t *> (buffer);
585  uint32_t size = 0;
586 
587  // Add the zero data length
588  if (size + 4 <= maxSize)
589  {
590  size += 4;
592  }
593  else
594  {
595  return 0;
596  }
597 
598  // Add the length of actual start data
599  uint32_t dataStartLength = m_zeroAreaStart - m_start;
600  if (size + 4 <= maxSize)
601  {
602  size += 4;
603  *p++ = dataStartLength;
604  }
605  else
606  {
607  return 0;
608  }
609 
610  // Add the actual data
611  if (size + ((dataStartLength + 3) & (~3)) <= maxSize)
612  {
613  size += (dataStartLength + 3) & (~3);
614  memcpy (p, m_data->m_data + m_start, dataStartLength);
615  p += (((dataStartLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
616  }
617  else
618  {
619  return 0;
620  }
621 
622  // Add the length of the actual end data
623  uint32_t dataEndLength = m_end - m_zeroAreaEnd;
624  if (size + 4 <= maxSize)
625  {
626  size += 4;
627  *p++ = dataEndLength;
628  }
629  else
630  {
631  return 0;
632  }
633 
634  // Add the actual data
635  if (size + ((dataEndLength + 3) & (~3)) <= maxSize)
636  {
637  // The following line is unnecessary.
638  // size += (dataEndLength + 3) & (~3);
639  memcpy (p, m_data->m_data+m_zeroAreaStart, dataEndLength);
640  // The following line is unnecessary.
641  // p += (((dataEndLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
642  }
643  else
644  {
645  return 0;
646  }
647 
648  // Serialized everything successfully
649  return 1;
650 }
651 
652 uint32_t
653 Buffer::Deserialize (const uint8_t *buffer, uint32_t size)
654 {
655  NS_LOG_FUNCTION (this << &buffer << size);
656  const uint32_t* p = reinterpret_cast<const uint32_t *> (buffer);
657  uint32_t sizeCheck = size-4;
658 
659  NS_ASSERT (sizeCheck >= 4);
660  uint32_t zeroDataLength = *p++;
661  sizeCheck -= 4;
662 
663  // Create zero bytes
664  Initialize (zeroDataLength);
665 
666  // Add start data
667  NS_ASSERT (sizeCheck >= 4);
668  uint32_t dataStartLength = *p++;
669  sizeCheck -= 4;
670  AddAtStart (dataStartLength);
671 
672  NS_ASSERT (sizeCheck >= dataStartLength);
673  Begin ().Write (reinterpret_cast<uint8_t *> (const_cast<uint32_t *> (p)), dataStartLength);
674  p += (((dataStartLength+3)&(~3))/4); // Advance p, insuring 4 byte boundary
675  sizeCheck -= ((dataStartLength+3)&(~3));
676 
677  // Add end data
678  NS_ASSERT (sizeCheck >= 4);
679  uint32_t dataEndLength = *p++;
680  sizeCheck -= 4;
681  AddAtEnd (dataEndLength);
682 
683  NS_ASSERT (sizeCheck >= dataEndLength);
684  Buffer::Iterator tmp = End ();
685  tmp.Prev (dataEndLength);
686  tmp.Write (reinterpret_cast<uint8_t *> (const_cast<uint32_t *> (p)), dataEndLength);
687  // The following line is unnecessary.
688  // p += (((dataEndLength+3)&(~3))/4); // Advance p, insuring 4 byte boundary
689  sizeCheck -= ((dataEndLength+3)&(~3));
690 
691  NS_ASSERT (sizeCheck == 0);
692  // return zero if buffer did not
693  // contain a complete message
694  return (sizeCheck != 0) ? 0 : 1;
695 }
696 
697 
698 void
700 {
701  NS_LOG_FUNCTION (this);
703  Buffer tmp = CreateFullCopy ();
704  *const_cast<Buffer *> (this) = tmp;
706 }
707 
708 
709 uint8_t const*
710 Buffer::PeekData (void) const
711 {
712  NS_LOG_FUNCTION (this);
716  return m_data->m_data + m_start;
717 }
718 
719 void
720 Buffer::CopyData (std::ostream *os, uint32_t size) const
721 {
722  NS_LOG_FUNCTION (this << &os << size);
723  if (size > 0)
724  {
725  uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size);
726  os->write ((const char*)(m_data->m_data + m_start), tmpsize);
727  if (size > tmpsize)
728  {
729  size -= m_zeroAreaStart-m_start;
730  tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size);
731  uint32_t left = tmpsize;
732  while (left > 0)
733  {
734  uint32_t toWrite = std::min (left, g_zeroes.size);
735  os->write (g_zeroes.buffer, toWrite);
736  left -= toWrite;
737  }
738  if (size > tmpsize)
739  {
740  size -= tmpsize;
741  tmpsize = std::min (m_end - m_zeroAreaEnd, size);
742  os->write ((const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
743  }
744  }
745  }
746 }
747 
748 uint32_t
749 Buffer::CopyData (uint8_t *buffer, uint32_t size) const
750 {
751  NS_LOG_FUNCTION (this << &buffer << size);
752  uint32_t originalSize = size;
753  if (size > 0)
754  {
755  uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size);
756  memcpy (buffer, (const char*)(m_data->m_data + m_start), tmpsize);
757  buffer += tmpsize;
758  size -= tmpsize;
759  if (size > 0)
760  {
761  tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size);
762  uint32_t left = tmpsize;
763  while (left > 0)
764  {
765  uint32_t toWrite = std::min (left, g_zeroes.size);
766  memcpy (buffer, g_zeroes.buffer, toWrite);
767  left -= toWrite;
768  buffer += toWrite;
769  }
770  size -= tmpsize;
771  if (size > 0)
772  {
773  tmpsize = std::min (m_end - m_zeroAreaEnd, size);
774  memcpy (buffer, (const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
775  size -= tmpsize;
776  }
777  }
778  }
779  return originalSize - size;
780 }
781 
782 /******************************************************
783  * The buffer iterator below.
784  ******************************************************/
785 
786 
787 uint32_t
789 {
790  NS_LOG_FUNCTION (this << &o);
791  NS_ASSERT (m_data == o.m_data);
792  int32_t diff = m_current - o.m_current;
793  if (diff < 0)
794  {
795  return -diff;
796  }
797  else
798  {
799  return diff;
800  }
801 }
802 
803 bool
805 {
806  NS_LOG_FUNCTION (this);
807  return m_current == m_dataEnd;
808 }
809 bool
811 {
812  NS_LOG_FUNCTION (this);
813  return m_current == m_dataStart;
814 }
815 
816 bool
817 Buffer::Iterator::CheckNoZero (uint32_t start, uint32_t end) const
818 {
819  NS_LOG_FUNCTION (this << &start << &end);
820  return !(start < m_dataStart ||
821  end > m_dataEnd ||
822  (end > m_zeroStart && start < m_zeroEnd && m_zeroEnd != m_zeroStart && start != end)
823  );
824 }
825 bool
826 Buffer::Iterator::Check (uint32_t i) const
827 {
828  NS_LOG_FUNCTION (this << &i);
829  return i >= m_dataStart &&
830  !(i >= m_zeroStart && i < m_zeroEnd) &&
831  i <= m_dataEnd;
832 }
833 
834 
835 void
837 {
838  NS_LOG_FUNCTION (this << &start << &end);
839  NS_ASSERT (start.m_data == end.m_data);
840  NS_ASSERT (start.m_current <= end.m_current);
841  NS_ASSERT (start.m_zeroStart == end.m_zeroStart);
842  NS_ASSERT (start.m_zeroEnd == end.m_zeroEnd);
843  NS_ASSERT (m_data != start.m_data);
844  uint32_t size = end.m_current - start.m_current;
845  NS_ASSERT_MSG (CheckNoZero (m_current, m_current + size),
846  GetWriteErrorMessage ());
847  if (start.m_current <= start.m_zeroStart)
848  {
849  uint32_t toCopy = std::min (size, start.m_zeroStart - start.m_current);
850  memcpy (&m_data[m_current], &start.m_data[start.m_current], toCopy);
851  start.m_current += toCopy;
852  m_current += toCopy;
853  size -= toCopy;
854  }
855  if (start.m_current <= start.m_zeroEnd)
856  {
857  uint32_t toCopy = std::min (size, start.m_zeroEnd - start.m_current);
858  memset (&m_data[m_current], 0, toCopy);
859  start.m_current += toCopy;
860  m_current += toCopy;
861  size -= toCopy;
862  }
863  uint32_t toCopy = std::min (size, start.m_dataEnd - start.m_current);
864  uint8_t *from = &start.m_data[start.m_current - (start.m_zeroEnd-start.m_zeroStart)];
865  uint8_t *to = &m_data[m_current];
866  memcpy (to, from, toCopy);
867  m_current += toCopy;
868 }
869 
870 void
872 {
873  NS_LOG_FUNCTION (this << data);
874  WriteU8 (data & 0xff);
875  data >>= 8;
876  WriteU8 (data & 0xff);
877 }
878 void
880 {
881  NS_LOG_FUNCTION (this << data);
882  WriteU8 (data & 0xff);
883  data >>= 8;
884  WriteU8 (data & 0xff);
885  data >>= 8;
886  WriteU8 (data & 0xff);
887  data >>= 8;
888  WriteU8 (data & 0xff);
889 }
890 void
892 {
893  NS_LOG_FUNCTION (this << data);
894  WriteU8 (data & 0xff);
895  data >>= 8;
896  WriteU8 (data & 0xff);
897  data >>= 8;
898  WriteU8 (data & 0xff);
899  data >>= 8;
900  WriteU8 (data & 0xff);
901  data >>= 8;
902  WriteU8 (data & 0xff);
903  data >>= 8;
904  WriteU8 (data & 0xff);
905  data >>= 8;
906  WriteU8 (data & 0xff);
907  data >>= 8;
908  WriteU8 (data & 0xff);
909 }
910 void
912 {
913  NS_LOG_FUNCTION (this << data);
914  WriteU8 ((data >> 0) & 0xff);
915  WriteU8 ((data >> 8) & 0xff);
916 }
917 void
919 {
920  NS_LOG_FUNCTION (this << data);
921  WriteU8 ((data >> 0) & 0xff);
922  WriteU8 ((data >> 8) & 0xff);
923  WriteU8 ((data >> 16) & 0xff);
924  WriteU8 ((data >> 24) & 0xff);
925 }
926 void
928 {
929  NS_LOG_FUNCTION (this << data);
930  WriteU8 ((data >> 0) & 0xff);
931  WriteU8 ((data >> 8) & 0xff);
932  WriteU8 ((data >> 16) & 0xff);
933  WriteU8 ((data >> 24) & 0xff);
934  WriteU8 ((data >> 32) & 0xff);
935  WriteU8 ((data >> 40) & 0xff);
936  WriteU8 ((data >> 48) & 0xff);
937  WriteU8 ((data >> 56) & 0xff);
938 }
939 
940 void
942 {
943  NS_LOG_FUNCTION (this << data);
944  WriteU8 ((data >> 56) & 0xff);
945  WriteU8 ((data >> 48) & 0xff);
946  WriteU8 ((data >> 40) & 0xff);
947  WriteU8 ((data >> 32) & 0xff);
948  WriteU8 ((data >> 24) & 0xff);
949  WriteU8 ((data >> 16) & 0xff);
950  WriteU8 ((data >> 8) & 0xff);
951  WriteU8 ((data >> 0) & 0xff);
952 }
953 void
954 Buffer::Iterator::Write (uint8_t const*buffer, uint32_t size)
955 {
956  NS_LOG_FUNCTION (this << &buffer << size);
957  NS_ASSERT_MSG (CheckNoZero (m_current, size),
958  GetWriteErrorMessage ());
959  uint8_t *to;
960  if (m_current <= m_zeroStart)
961  {
962  to = &m_data[m_current];
963  }
964  else
965  {
966  to = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
967  }
968  memcpy (to, buffer, size);
969  m_current += size;
970 }
971 
972 uint32_t
974 {
975  NS_LOG_FUNCTION (this);
976  uint8_t byte0 = ReadU8 ();
977  uint8_t byte1 = ReadU8 ();
978  uint8_t byte2 = ReadU8 ();
979  uint8_t byte3 = ReadU8 ();
980  uint32_t data = byte3;
981  data <<= 8;
982  data |= byte2;
983  data <<= 8;
984  data |= byte1;
985  data <<= 8;
986  data |= byte0;
987  return data;
988 }
989 uint64_t
991 {
992  NS_LOG_FUNCTION (this);
993  uint8_t byte0 = ReadU8 ();
994  uint8_t byte1 = ReadU8 ();
995  uint8_t byte2 = ReadU8 ();
996  uint8_t byte3 = ReadU8 ();
997  uint8_t byte4 = ReadU8 ();
998  uint8_t byte5 = ReadU8 ();
999  uint8_t byte6 = ReadU8 ();
1000  uint8_t byte7 = ReadU8 ();
1001  uint64_t data = byte7;
1002  data <<= 8;
1003  data |= byte6;
1004  data <<= 8;
1005  data |= byte5;
1006  data <<= 8;
1007  data |= byte4;
1008  data <<= 8;
1009  data |= byte3;
1010  data <<= 8;
1011  data |= byte2;
1012  data <<= 8;
1013  data |= byte1;
1014  data <<= 8;
1015  data |= byte0;
1016 
1017  return data;
1018 }
1019 uint16_t
1021 {
1022  NS_LOG_FUNCTION (this);
1023  uint16_t retval = 0;
1024  retval |= ReadU8 ();
1025  retval <<= 8;
1026  retval |= ReadU8 ();
1027  return retval;
1028 }
1029 uint32_t
1031 {
1032  NS_LOG_FUNCTION (this);
1033  uint32_t retval = 0;
1034  retval |= ReadU8 ();
1035  retval <<= 8;
1036  retval |= ReadU8 ();
1037  retval <<= 8;
1038  retval |= ReadU8 ();
1039  retval <<= 8;
1040  retval |= ReadU8 ();
1041  return retval;
1042 }
1043 uint64_t
1045 {
1046  NS_LOG_FUNCTION (this);
1047  uint64_t retval = 0;
1048  retval |= ReadU8 ();
1049  retval <<= 8;
1050  retval |= ReadU8 ();
1051  retval <<= 8;
1052  retval |= ReadU8 ();
1053  retval <<= 8;
1054  retval |= ReadU8 ();
1055  retval <<= 8;
1056  retval |= ReadU8 ();
1057  retval <<= 8;
1058  retval |= ReadU8 ();
1059  retval <<= 8;
1060  retval |= ReadU8 ();
1061  retval <<= 8;
1062  retval |= ReadU8 ();
1063  return retval;
1064 }
1065 uint16_t
1067 {
1068  NS_LOG_FUNCTION (this);
1069  uint8_t byte0 = ReadU8 ();
1070  uint8_t byte1 = ReadU8 ();
1071  uint16_t data = byte1;
1072  data <<= 8;
1073  data |= byte0;
1074  return data;
1075 }
1076 uint32_t
1078 {
1079  NS_LOG_FUNCTION (this);
1080  uint8_t byte0 = ReadU8 ();
1081  uint8_t byte1 = ReadU8 ();
1082  uint8_t byte2 = ReadU8 ();
1083  uint8_t byte3 = ReadU8 ();
1084  uint32_t data = byte3;
1085  data <<= 8;
1086  data |= byte2;
1087  data <<= 8;
1088  data |= byte1;
1089  data <<= 8;
1090  data |= byte0;
1091  return data;
1092 }
1093 uint64_t
1095 {
1096  NS_LOG_FUNCTION (this);
1097  uint8_t byte0 = ReadU8 ();
1098  uint8_t byte1 = ReadU8 ();
1099  uint8_t byte2 = ReadU8 ();
1100  uint8_t byte3 = ReadU8 ();
1101  uint8_t byte4 = ReadU8 ();
1102  uint8_t byte5 = ReadU8 ();
1103  uint8_t byte6 = ReadU8 ();
1104  uint8_t byte7 = ReadU8 ();
1105  uint64_t data = byte7;
1106  data <<= 8;
1107  data |= byte6;
1108  data <<= 8;
1109  data |= byte5;
1110  data <<= 8;
1111  data |= byte4;
1112  data <<= 8;
1113  data |= byte3;
1114  data <<= 8;
1115  data |= byte2;
1116  data <<= 8;
1117  data |= byte1;
1118  data <<= 8;
1119  data |= byte0;
1120 
1121  return data;
1122 }
1123 void
1124 Buffer::Iterator::Read (uint8_t *buffer, uint32_t size)
1125 {
1126  NS_LOG_FUNCTION (this << &buffer << size);
1127  for (uint32_t i = 0; i < size; i++)
1128  {
1129  buffer[i] = ReadU8 ();
1130  }
1131 }
1132 
1133 uint16_t
1135 {
1136  NS_LOG_FUNCTION (this << size);
1137  return CalculateIpChecksum (size, 0);
1138 }
1139 
1140 uint16_t
1141 Buffer::Iterator::CalculateIpChecksum (uint16_t size, uint32_t initialChecksum)
1142 {
1143  NS_LOG_FUNCTION (this << size << initialChecksum);
1144  /* see RFC 1071 to understand this code. */
1145  uint32_t sum = initialChecksum;
1146 
1147  for (int j = 0; j < size/2; j++)
1148  sum += ReadU16 ();
1149 
1150  if (size & 1)
1151  sum += ReadU8 ();
1152 
1153  while (sum >> 16)
1154  sum = (sum & 0xffff) + (sum >> 16);
1155  return ~sum;
1156 }
1157 
1158 uint32_t
1160 {
1161  NS_LOG_FUNCTION (this);
1162  return m_dataEnd - m_dataStart;
1163 }
1164 
1165 uint32_t
1167 {
1168  NS_LOG_FUNCTION (this);
1169  return m_dataEnd - m_current;
1170 }
1171 
1172 
1173 std::string
1175 {
1176  NS_LOG_FUNCTION (this);
1177  std::string str = "You have attempted to read beyond the bounds of the "
1178  "available buffer space. This usually indicates that a "
1179  "Header::Deserialize or Trailer::Deserialize method "
1180  "is trying to read data which was not written by "
1181  "a Header::Serialize or Trailer::Serialize method. "
1182  "In short: check the code of your Serialize and Deserialize "
1183  "methods.";
1184  return str;
1185 }
1186 std::string
1188 {
1189  NS_LOG_FUNCTION (this);
1190  std::string str;
1191  if (m_current < m_dataStart)
1192  {
1193  str = "You have attempted to write before the start of the available "
1194  "buffer space. This usually indicates that Trailer::GetSerializedSize "
1195  "returned a size which is too small compared to what Trailer::Serialize "
1196  "is actually using.";
1197  }
1198  else if (m_current >= m_dataEnd)
1199  {
1200  str = "You have attempted to write after the end of the available "
1201  "buffer space. This usually indicates that Header::GetSerializedSize "
1202  "returned a size which is too small compared to what Header::Serialize "
1203  "is actually using.";
1204  }
1205  else
1206  {
1207  NS_ASSERT (m_current >= m_zeroStart && m_current < m_zeroEnd);
1208  str = "You have attempted to write inside the payload area of the "
1209  "buffer. This usually indicates that your Serialize method uses more "
1210  "buffer space than what your GetSerialized method returned.";
1211  }
1212  return str;
1213 }
1214 
1215 
1216 } // namespace ns3
1217 
1218 
#define min(a, b)
Definition: 80211b.c:42
#define max(a, b)
Definition: 80211b.c:43
#define LOG_INTERNAL_STATE(y)
Definition: buffer.cc:24
#define IS_UNINITIALIZED(x)
Definition: buffer.cc:73
#define DESTROYED
Definition: buffer.cc:76
#define IS_INITIALIZED(x)
Definition: buffer.cc:75
#define IS_DESTROYED(x)
Definition: buffer.cc:74
iterator in a Buffer instance
Definition: buffer.h:99
void WriteU64(uint64_t data)
Definition: buffer.cc:891
void Write(uint8_t const *buffer, uint32_t size)
Definition: buffer.cc:954
void WriteU32(uint32_t data)
Definition: buffer.cc:879
bool IsEnd(void) const
Definition: buffer.cc:804
bool IsStart(void) const
Definition: buffer.cc:810
void WriteHtonU64(uint64_t data)
Definition: buffer.cc:941
void WriteHtolsbU16(uint16_t data)
Definition: buffer.cc:911
uint64_t ReadNtohU64(void)
Definition: buffer.cc:1044
uint32_t ReadLsbtohU32(void)
Definition: buffer.cc:1077
uint16_t CalculateIpChecksum(uint16_t size)
Calculate the checksum.
Definition: buffer.cc:1134
void WriteU8(uint8_t data)
Definition: buffer.h:869
uint8_t * m_data
a pointer to the underlying byte buffer.
Definition: buffer.h:484
uint32_t GetRemainingSize(void) const
Definition: buffer.cc:1166
void WriteHtolsbU32(uint32_t data)
Definition: buffer.cc:918
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:464
bool Check(uint32_t i) const
Checks that the buffer position is not in the "virtual zero area".
Definition: buffer.cc:826
uint32_t SlowReadNtohU32(void)
Definition: buffer.cc:1030
void WriteU16(uint16_t data)
Definition: buffer.cc:871
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:479
void Read(uint8_t *buffer, uint32_t size)
Definition: buffer.cc:1124
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:927
uint16_t ReadLsbtohU16(void)
Definition: buffer.cc:1066
void Prev(void)
go backward by one byte
Definition: buffer.h:851
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:459
std::string GetWriteErrorMessage(void) const
Returns an appropriate message indicating a write error.
Definition: buffer.cc:1187
uint64_t ReadLsbtohU64(void)
Definition: buffer.cc:1094
uint16_t SlowReadNtohU16(void)
Definition: buffer.cc:1020
uint64_t ReadU64(void)
Definition: buffer.cc:990
bool CheckNoZero(uint32_t start, uint32_t end) const
Checks that the [start, end) is not in the "virtual zero area".
Definition: buffer.cc:817
uint32_t GetDistanceFrom(Iterator const &o) const
Definition: buffer.cc:788
std::string GetReadErrorMessage(void) const
Returns an appropriate message indicating a read error.
Definition: buffer.cc:1174
uint32_t GetSize(void) const
Definition: buffer.cc:1159
uint32_t ReadU32(void)
Definition: buffer.cc:973
automatically resized byte buffer
Definition: buffer.h:93
uint32_t GetInternalSize(void) const
Get the buffer real size.
Definition: buffer.cc:296
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:791
bool CheckInternalState(void) const
Checks the internal buffer structures consistency.
Definition: buffer.cc:210
Buffer CreateFragment(uint32_t start, uint32_t length) const
Definition: buffer.cc:524
static FreeList * g_freeList
Buffer data container.
Definition: buffer.h:802
static struct Buffer::Data * Create(uint32_t size)
Create a buffer data storage.
Definition: buffer.cc:119
static uint32_t g_maxSize
Max observed data size.
Definition: buffer.h:801
uint32_t m_zeroAreaEnd
offset to the end of the virtual zero area from the start of m_data->m_data
Definition: buffer.h:781
std::vector< struct Buffer::Data * > FreeList
Container for buffer data.
Definition: buffer.h:795
static void Deallocate(struct Buffer::Data *data)
Deallocate the buffer memory.
Definition: buffer.cc:180
uint32_t m_maxZeroAreaStart
keep track of the maximum value of m_zeroAreaStart across the lifetime of a Buffer instance.
Definition: buffer.h:764
uint32_t GetSize(void) const
Definition: buffer.h:1063
static uint32_t g_recommendedStart
location in a newly-allocated buffer where you should start writing data.
Definition: buffer.h:770
uint32_t GetInternalEnd(void) const
Get the buffer end position.
Definition: buffer.cc:302
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:720
Buffer CreateFullCopy(void) const
Create a full copy of the buffer, including all the internal structures.
Definition: buffer.cc:536
static struct Buffer::Data * Allocate(uint32_t reqSize)
Allocate a buffer data storage.
Definition: buffer.cc:163
Buffer & operator=(Buffer const &o)
Assignment operator.
Definition: buffer.cc:259
void RemoveAtEnd(uint32_t end)
Definition: buffer.cc:488
void AddAtStart(uint32_t start)
Definition: buffer.cc:309
void AddAtEnd(uint32_t end)
Definition: buffer.cc:354
uint32_t GetSerializedSize(void) const
Return the number of bytes required for serialization.
Definition: buffer.cc:561
void TransformIntoRealBuffer(void) const
Transform a "Virtual byte buffer" into a "Real byte buffer".
Definition: buffer.cc:699
static void Recycle(struct Buffer::Data *data)
Recycle the buffer memory.
Definition: buffer.cc:98
struct Data * m_data
the buffer data storage
Definition: buffer.h:752
Buffer::Iterator End(void) const
Definition: buffer.h:1075
uint8_t const * PeekData(void) const
Definition: buffer.cc:710
void Initialize(uint32_t zeroSize)
Initializes the buffer with a number of zeroes.
Definition: buffer.cc:244
Buffer::Iterator Begin(void) const
Definition: buffer.h:1069
uint32_t Deserialize(const uint8_t *buffer, uint32_t size)
Definition: buffer.cc:653
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:443
uint32_t m_zeroAreaStart
offset to the start of the virtual zero area from the start of m_data->m_data
Definition: buffer.h:776
uint32_t Serialize(uint8_t *buffer, uint32_t maxSize) const
Definition: buffer.cc:581
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:786
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#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:88
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
static struct anonymous_namespace{buffer.cc}::Zeroes g_zeroes
Zero-filled buffer.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
def start()
Definition: core.py:1853
uint8_t data[writeSize]
char buffer[1000]
buffer containing zero values
Definition: buffer.cc:42
const uint32_t size
buffer size
Definition: buffer.cc:43
This data structure is variable-sized through its last member whose size is determined at allocation ...
Definition: buffer.h:661
uint8_t m_data[1]
The real data buffer holds at least one byte.
Definition: buffer.h:685
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:680
uint32_t m_count
The reference count of an instance of this data structure.
Definition: buffer.h:666
uint32_t m_size
the size of the m_data field below.
Definition: buffer.h:670
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:675
Local static destructor structure.
Definition: buffer.h:798