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