A Discrete-Event Network Simulator
API
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 struct Buffer::LocalStaticDestructor Buffer::g_localStaticDestructor;
85 
87 {
88  NS_LOG_FUNCTION(this);
90  {
91  for (Buffer::FreeList::iterator 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  struct 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  struct 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 struct Buffer::Data*
164 Buffer::Allocate(uint32_t reqSize)
165 {
166  NS_LOG_FUNCTION(reqSize);
167  if (reqSize == 0)
168  {
169  reqSize = 1;
170  }
171  NS_ASSERT(reqSize >= 1);
172  uint32_t size = reqSize - 1 + sizeof(struct Buffer::Data);
173  uint8_t* b = new uint8_t[size];
174  struct Buffer::Data* data = reinterpret_cast<struct Buffer::Data*>(b);
175  data->m_size = reqSize;
176  data->m_count = 1;
177  return data;
178 }
179 
180 void
182 {
184  NS_ASSERT(data->m_count == 0);
185  uint8_t* buf = reinterpret_cast<uint8_t*>(data);
186  delete[] buf;
187 }
188 
190 {
191  NS_LOG_FUNCTION(this);
192  Initialize(0);
193 }
194 
195 Buffer::Buffer(uint32_t dataSize)
196 {
197  NS_LOG_FUNCTION(this << dataSize);
198  Initialize(dataSize);
199 }
200 
201 Buffer::Buffer(uint32_t dataSize, bool initialize)
202 {
203  NS_LOG_FUNCTION(this << dataSize << initialize);
204  if (initialize == true)
205  {
206  Initialize(dataSize);
207  }
208 }
209 
210 bool
212 {
213  NS_LOG_FUNCTION(this);
214 #if 0
215  // If you want to modify any code in this file, enable this checking code.
216  // Otherwise, there is not much point is enabling it because the
217  // current implementation has been fairly seriously tested and the cost
218  // of this constant checking is pretty high, even for a debug build.
219  bool offsetsOk =
222  m_zeroAreaEnd <= m_end;
223  bool dirtyOk =
225  m_end <= m_data->m_dirtyEnd;
226  bool internalSizeOk = m_end - (m_zeroAreaEnd - m_zeroAreaStart) <= m_data->m_size &&
227  m_start <= m_data->m_size &&
228  m_zeroAreaStart <= m_data->m_size;
229 
230  bool ok = m_data->m_count > 0 && offsetsOk && dirtyOk && internalSizeOk;
231  if (!ok)
232  {
233  LOG_INTERNAL_STATE ("check " << this <<
234  ", " << (offsetsOk ? "true" : "false") <<
235  ", " << (dirtyOk ? "true" : "false") <<
236  ", " << (internalSizeOk ? "true" : "false") << " ");
237  }
238  return ok;
239 #else
240  return true;
241 #endif
242 }
243 
244 void
245 Buffer::Initialize(uint32_t zeroSize)
246 {
247  NS_LOG_FUNCTION(this << zeroSize);
248  m_data = Buffer::Create(0);
252  m_zeroAreaEnd = m_zeroAreaStart + zeroSize;
257 }
258 
259 Buffer&
261 {
263  if (m_data != o.m_data)
264  {
265  // not assignment to self.
266  m_data->m_count--;
267  if (m_data->m_count == 0)
268  {
269  Recycle(m_data);
270  }
271  m_data = o.m_data;
272  m_data->m_count++;
273  }
278  m_start = o.m_start;
279  m_end = o.m_end;
281  return *this;
282 }
283 
285 {
286  NS_LOG_FUNCTION(this);
289  m_data->m_count--;
290  if (m_data->m_count == 0)
291  {
292  Recycle(m_data);
293  }
294 }
295 
296 uint32_t
298 {
299  NS_LOG_FUNCTION(this);
301 }
302 
303 uint32_t
305 {
306  NS_LOG_FUNCTION(this);
307  return m_end - (m_zeroAreaEnd - m_zeroAreaStart);
308 }
309 
310 void
312 {
313  NS_LOG_FUNCTION(this << start);
315  bool isDirty = m_data->m_count > 1 && m_start > m_data->m_dirtyStart;
316  if (m_start >= start && !isDirty)
317  {
318  /* enough space in the buffer and not dirty.
319  * To add: |..|
320  * Before: |*****---------***|
321  * After: |***..---------***|
322  */
324  m_start -= start;
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;
343  m_zeroAreaEnd += delta;
344  m_end += delta;
345  m_start -= start;
346 
347  // update dirty area
350  }
352  LOG_INTERNAL_STATE("add start=" << start << ", ");
354 }
355 
356 void
357 Buffer::AddAtEnd(uint32_t end)
358 {
359  NS_LOG_FUNCTION(this << end);
361  bool isDirty = m_data->m_count > 1 && m_end < m_data->m_dirtyEnd;
362  if (GetInternalEnd() + end <= m_data->m_size && !isDirty)
363  {
364  /* enough space in buffer and not dirty
365  * Add: |...|
366  * Before: |**----*****|
367  * After: |**----...**|
368  */
370  m_end += end;
371  // update dirty area.
373  }
374  else
375  {
376  uint32_t newSize = GetInternalSize() + end;
377  struct Buffer::Data* newData = Buffer::Create(newSize);
378  memcpy(newData->m_data, m_data->m_data + m_start, GetInternalSize());
379  m_data->m_count--;
380  if (m_data->m_count == 0)
381  {
383  }
384  m_data = newData;
385 
386  int32_t delta = -m_start;
388  m_zeroAreaEnd += delta;
389  m_end += delta;
390  m_start += delta;
391  m_end += end;
392 
393  // update dirty area
396  }
398  LOG_INTERNAL_STATE("add end=" << end << ", ");
400 }
401 
402 void
404 {
405  NS_LOG_FUNCTION(this << &o);
406 
409  o.m_zeroAreaEnd - o.m_zeroAreaStart > 0)
410  {
417  {
419  }
420  uint32_t zeroSize = o.m_zeroAreaEnd - o.m_zeroAreaStart;
421  m_zeroAreaEnd = m_end + zeroSize;
424  uint32_t endData = o.m_end - o.m_zeroAreaEnd;
425  AddAtEnd(endData);
426  Buffer::Iterator dst = End();
427  dst.Prev(endData);
428  Buffer::Iterator src = o.End();
429  src.Prev(endData);
430  dst.Write(src, o.End());
432  return;
433  }
434 
435  *this = CreateFullCopy();
436  AddAtEnd(o.GetSize());
437  Buffer::Iterator destStart = End();
438  destStart.Prev(o.GetSize());
439  destStart.Write(o.Begin(), o.End());
441 }
442 
443 void
445 {
446  NS_LOG_FUNCTION(this << start);
448  uint32_t newStart = m_start + start;
449  if (newStart <= m_zeroAreaStart)
450  {
451  /* only remove start of buffer
452  */
453  m_start = newStart;
454  }
455  else if (newStart <= m_zeroAreaEnd)
456  {
457  /* remove start of buffer _and_ start of zero area
458  */
459  uint32_t delta = newStart - m_zeroAreaStart;
461  m_zeroAreaEnd -= delta;
462  m_end -= delta;
463  }
464  else if (newStart <= m_end)
465  {
466  /* remove start of buffer, complete zero area, and part
467  * of end of buffer
468  */
469  NS_ASSERT(m_end >= start);
470  uint32_t zeroSize = m_zeroAreaEnd - m_zeroAreaStart;
471  m_start = newStart - zeroSize;
472  m_end -= zeroSize;
475  }
476  else
477  {
478  /* remove all buffer */
480  m_start = m_end;
483  }
485  LOG_INTERNAL_STATE("rem start=" << start << ", ");
487 }
488 
489 void
490 Buffer::RemoveAtEnd(uint32_t end)
491 {
492  NS_LOG_FUNCTION(this << end);
494  uint32_t newEnd = m_end - std::min(end, m_end - m_start);
495  if (newEnd > m_zeroAreaEnd)
496  {
497  /* remove part of end of buffer */
498  m_end = newEnd;
499  }
500  else if (newEnd > m_zeroAreaStart)
501  {
502  /* remove end of buffer, part of zero area */
503  m_end = newEnd;
504  m_zeroAreaEnd = newEnd;
505  }
506  else if (newEnd > m_start)
507  {
508  /* remove end of buffer, zero area, part of start of buffer */
509  m_end = newEnd;
510  m_zeroAreaEnd = newEnd;
511  m_zeroAreaStart = newEnd;
512  }
513  else
514  {
515  /* remove all buffer */
516  m_end = m_start;
519  }
521  LOG_INTERNAL_STATE("rem end=" << end << ", ");
523 }
524 
525 Buffer
526 Buffer::CreateFragment(uint32_t start, uint32_t length) const
527 {
528  NS_LOG_FUNCTION(this << start << length);
530  Buffer tmp = *this;
531  tmp.RemoveAtStart(start);
532  tmp.RemoveAtEnd(GetSize() - (start + length));
534  return tmp;
535 }
536 
537 Buffer
539 {
540  NS_LOG_FUNCTION(this);
542  if (m_zeroAreaEnd - m_zeroAreaStart != 0)
543  {
544  Buffer tmp;
547  uint32_t dataStart = m_zeroAreaStart - m_start;
548  tmp.AddAtStart(dataStart);
549  tmp.Begin().Write(m_data->m_data + m_start, dataStart);
550  uint32_t dataEnd = m_end - m_zeroAreaEnd;
551  tmp.AddAtEnd(dataEnd);
552  Buffer::Iterator i = tmp.End();
553  i.Prev(dataEnd);
554  i.Write(m_data->m_data + m_zeroAreaStart, dataEnd);
556  return tmp;
557  }
559  return *this;
560 }
561 
562 uint32_t
564 {
565  NS_LOG_FUNCTION(this);
566  uint32_t dataStart = (m_zeroAreaStart - m_start + 3) & (~0x3);
567  uint32_t dataEnd = (m_end - m_zeroAreaEnd + 3) & (~0x3);
568 
569  // total size 4-bytes for dataStart length
570  // + X number of bytes for dataStart
571  // + 4-bytes for dataEnd length
572  // + X number of bytes for dataEnd
573  uint32_t sz = sizeof(uint32_t) + sizeof(uint32_t) + dataStart + sizeof(uint32_t) + dataEnd;
574 
575  return sz;
576 }
577 
578 uint32_t
579 Buffer::Serialize(uint8_t* buffer, uint32_t maxSize) const
580 {
581  NS_LOG_FUNCTION(this << &buffer << maxSize);
582  uint32_t* p = reinterpret_cast<uint32_t*>(buffer);
583  uint32_t size = 0;
584 
585  // Add the zero data length
586  if (size + 4 <= maxSize)
587  {
588  size += 4;
590  }
591  else
592  {
593  return 0;
594  }
595 
596  // Add the length of actual start data
597  uint32_t dataStartLength = m_zeroAreaStart - m_start;
598  if (size + 4 <= maxSize)
599  {
600  size += 4;
601  *p++ = dataStartLength;
602  }
603  else
604  {
605  return 0;
606  }
607 
608  // Add the actual data
609  if (size + ((dataStartLength + 3) & (~3)) <= maxSize)
610  {
611  size += (dataStartLength + 3) & (~3);
612  memcpy(p, m_data->m_data + m_start, dataStartLength);
613  p += (((dataStartLength + 3) & (~3)) / 4); // Advance p, insuring 4 byte boundary
614  }
615  else
616  {
617  return 0;
618  }
619 
620  // Add the length of the actual end data
621  uint32_t dataEndLength = m_end - m_zeroAreaEnd;
622  if (size + 4 <= maxSize)
623  {
624  size += 4;
625  *p++ = dataEndLength;
626  }
627  else
628  {
629  return 0;
630  }
631 
632  // Add the actual data
633  if (size + ((dataEndLength + 3) & (~3)) <= maxSize)
634  {
635  // The following line is unnecessary.
636  // size += (dataEndLength + 3) & (~3);
637  memcpy(p, m_data->m_data + m_zeroAreaStart, dataEndLength);
638  // The following line is unnecessary.
639  // p += (((dataEndLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
640  }
641  else
642  {
643  return 0;
644  }
645 
646  // Serialized everything successfully
647  return 1;
648 }
649 
650 uint32_t
651 Buffer::Deserialize(const uint8_t* buffer, uint32_t size)
652 {
653  NS_LOG_FUNCTION(this << &buffer << size);
654  const uint32_t* p = reinterpret_cast<const uint32_t*>(buffer);
655  uint32_t sizeCheck = size - 4;
656 
657  NS_ASSERT(sizeCheck >= 4);
658  uint32_t zeroDataLength = *p++;
659  sizeCheck -= 4;
660 
661  // Create zero bytes
662  Initialize(zeroDataLength);
663 
664  // Add start data
665  NS_ASSERT(sizeCheck >= 4);
666  uint32_t dataStartLength = *p++;
667  sizeCheck -= 4;
668  AddAtStart(dataStartLength);
669 
670  NS_ASSERT(sizeCheck >= dataStartLength);
671  Begin().Write(reinterpret_cast<uint8_t*>(const_cast<uint32_t*>(p)), dataStartLength);
672  p += (((dataStartLength + 3) & (~3)) / 4); // Advance p, insuring 4 byte boundary
673  sizeCheck -= ((dataStartLength + 3) & (~3));
674 
675  // Add end data
676  NS_ASSERT(sizeCheck >= 4);
677  uint32_t dataEndLength = *p++;
678  sizeCheck -= 4;
679  AddAtEnd(dataEndLength);
680 
681  NS_ASSERT(sizeCheck >= dataEndLength);
682  Buffer::Iterator tmp = End();
683  tmp.Prev(dataEndLength);
684  tmp.Write(reinterpret_cast<uint8_t*>(const_cast<uint32_t*>(p)), dataEndLength);
685  // The following line is unnecessary.
686  // p += (((dataEndLength+3)&(~3))/4); // Advance p, insuring 4 byte boundary
687  sizeCheck -= ((dataEndLength + 3) & (~3));
688 
689  NS_ASSERT(sizeCheck == 0);
690  // return zero if buffer did not
691  // contain a complete message
692  return (sizeCheck != 0) ? 0 : 1;
693 }
694 
695 void
697 {
698  NS_LOG_FUNCTION(this);
700  Buffer tmp = CreateFullCopy();
701  *const_cast<Buffer*>(this) = tmp;
703 }
704 
705 const uint8_t*
707 {
708  NS_LOG_FUNCTION(this);
712  return m_data->m_data + m_start;
713 }
714 
715 void
716 Buffer::CopyData(std::ostream* os, uint32_t size) const
717 {
718  NS_LOG_FUNCTION(this << &os << size);
719  if (size > 0)
720  {
721  uint32_t tmpsize = std::min(m_zeroAreaStart - m_start, size);
722  os->write((const char*)(m_data->m_data + m_start), tmpsize);
723  if (size > tmpsize)
724  {
725  size -= m_zeroAreaStart - m_start;
726  tmpsize = std::min(m_zeroAreaEnd - m_zeroAreaStart, size);
727  uint32_t left = tmpsize;
728  while (left > 0)
729  {
730  uint32_t toWrite = std::min(left, g_zeroes.size);
731  os->write(g_zeroes.buffer, toWrite);
732  left -= toWrite;
733  }
734  if (size > tmpsize)
735  {
736  size -= tmpsize;
737  tmpsize = std::min(m_end - m_zeroAreaEnd, size);
738  os->write((const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
739  }
740  }
741  }
742 }
743 
744 uint32_t
745 Buffer::CopyData(uint8_t* buffer, uint32_t size) const
746 {
747  NS_LOG_FUNCTION(this << &buffer << size);
748  uint32_t originalSize = size;
749  if (size > 0)
750  {
751  uint32_t tmpsize = std::min(m_zeroAreaStart - m_start, size);
752  memcpy(buffer, (const char*)(m_data->m_data + m_start), tmpsize);
753  buffer += tmpsize;
754  size -= tmpsize;
755  if (size > 0)
756  {
757  tmpsize = std::min(m_zeroAreaEnd - m_zeroAreaStart, size);
758  uint32_t left = tmpsize;
759  while (left > 0)
760  {
761  uint32_t toWrite = std::min(left, g_zeroes.size);
762  memcpy(buffer, g_zeroes.buffer, toWrite);
763  left -= toWrite;
764  buffer += toWrite;
765  }
766  size -= tmpsize;
767  if (size > 0)
768  {
769  tmpsize = std::min(m_end - m_zeroAreaEnd, size);
770  memcpy(buffer, (const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
771  size -= tmpsize;
772  }
773  }
774  }
775  return originalSize - size;
776 }
777 
778 /******************************************************
779  * The buffer iterator below.
780  ******************************************************/
781 
782 uint32_t
784 {
785  NS_LOG_FUNCTION(this << &o);
786  NS_ASSERT(m_data == o.m_data);
787  int32_t diff = m_current - o.m_current;
788  if (diff < 0)
789  {
790  return -diff;
791  }
792  else
793  {
794  return diff;
795  }
796 }
797 
798 bool
800 {
801  NS_LOG_FUNCTION(this);
802  return m_current == m_dataEnd;
803 }
804 
805 bool
807 {
808  NS_LOG_FUNCTION(this);
809  return m_current == m_dataStart;
810 }
811 
812 bool
813 Buffer::Iterator::CheckNoZero(uint32_t start, uint32_t end) const
814 {
815  NS_LOG_FUNCTION(this << &start << &end);
816  return !(start < m_dataStart || end > m_dataEnd ||
817  (end > m_zeroStart && start < m_zeroEnd && m_zeroEnd != m_zeroStart && start != end));
818 }
819 
820 bool
821 Buffer::Iterator::Check(uint32_t i) const
822 {
823  NS_LOG_FUNCTION(this << &i);
824  return i >= m_dataStart && !(i >= m_zeroStart && i < m_zeroEnd) && i <= m_dataEnd;
825 }
826 
827 void
829 {
830  NS_LOG_FUNCTION(this << &start << &end);
831  NS_ASSERT(start.m_data == end.m_data);
832  NS_ASSERT(start.m_current <= end.m_current);
833  NS_ASSERT(start.m_zeroStart == end.m_zeroStart);
834  NS_ASSERT(start.m_zeroEnd == end.m_zeroEnd);
835  NS_ASSERT(m_data != start.m_data);
836  uint32_t size = end.m_current - start.m_current;
837  NS_ASSERT_MSG(CheckNoZero(m_current, m_current + size), GetWriteErrorMessage());
838  if (start.m_current <= start.m_zeroStart)
839  {
840  uint32_t toCopy = std::min(size, start.m_zeroStart - start.m_current);
841  memcpy(&m_data[m_current], &start.m_data[start.m_current], toCopy);
842  start.m_current += toCopy;
843  m_current += toCopy;
844  size -= toCopy;
845  }
846  if (start.m_current <= start.m_zeroEnd)
847  {
848  uint32_t toCopy = std::min(size, start.m_zeroEnd - start.m_current);
849  memset(&m_data[m_current], 0, toCopy);
850  start.m_current += toCopy;
851  m_current += toCopy;
852  size -= toCopy;
853  }
854  uint32_t toCopy = std::min(size, start.m_dataEnd - start.m_current);
855  uint8_t* from = &start.m_data[start.m_current - (start.m_zeroEnd - start.m_zeroStart)];
856  uint8_t* to = &m_data[m_current];
857  memcpy(to, from, toCopy);
858  m_current += toCopy;
859 }
860 
861 void
863 {
864  NS_LOG_FUNCTION(this << data);
865  WriteU8(data & 0xff);
866  data >>= 8;
867  WriteU8(data & 0xff);
868 }
869 
870 void
872 {
873  NS_LOG_FUNCTION(this << data);
874  WriteU8(data & 0xff);
875  data >>= 8;
876  WriteU8(data & 0xff);
877  data >>= 8;
878  WriteU8(data & 0xff);
879  data >>= 8;
880  WriteU8(data & 0xff);
881 }
882 
883 void
885 {
886  NS_LOG_FUNCTION(this << data);
887  WriteU8(data & 0xff);
888  data >>= 8;
889  WriteU8(data & 0xff);
890  data >>= 8;
891  WriteU8(data & 0xff);
892  data >>= 8;
893  WriteU8(data & 0xff);
894  data >>= 8;
895  WriteU8(data & 0xff);
896  data >>= 8;
897  WriteU8(data & 0xff);
898  data >>= 8;
899  WriteU8(data & 0xff);
900  data >>= 8;
901  WriteU8(data & 0xff);
902 }
903 
904 void
906 {
907  NS_LOG_FUNCTION(this << data);
908  WriteU8((data >> 0) & 0xff);
909  WriteU8((data >> 8) & 0xff);
910 }
911 
912 void
914 {
915  NS_LOG_FUNCTION(this << data);
916  WriteU8((data >> 0) & 0xff);
917  WriteU8((data >> 8) & 0xff);
918  WriteU8((data >> 16) & 0xff);
919  WriteU8((data >> 24) & 0xff);
920 }
921 
922 void
924 {
925  NS_LOG_FUNCTION(this << data);
926  WriteU8((data >> 0) & 0xff);
927  WriteU8((data >> 8) & 0xff);
928  WriteU8((data >> 16) & 0xff);
929  WriteU8((data >> 24) & 0xff);
930  WriteU8((data >> 32) & 0xff);
931  WriteU8((data >> 40) & 0xff);
932  WriteU8((data >> 48) & 0xff);
933  WriteU8((data >> 56) & 0xff);
934 }
935 
936 void
938 {
939  NS_LOG_FUNCTION(this << data);
940  WriteU8((data >> 56) & 0xff);
941  WriteU8((data >> 48) & 0xff);
942  WriteU8((data >> 40) & 0xff);
943  WriteU8((data >> 32) & 0xff);
944  WriteU8((data >> 24) & 0xff);
945  WriteU8((data >> 16) & 0xff);
946  WriteU8((data >> 8) & 0xff);
947  WriteU8((data >> 0) & 0xff);
948 }
949 
950 void
951 Buffer::Iterator::Write(const uint8_t* buffer, uint32_t size)
952 {
953  NS_LOG_FUNCTION(this << &buffer << size);
954  NS_ASSERT_MSG(CheckNoZero(m_current, size), GetWriteErrorMessage());
955  uint8_t* to;
956  if (m_current <= m_zeroStart)
957  {
958  to = &m_data[m_current];
959  }
960  else
961  {
962  to = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
963  }
964  memcpy(to, buffer, size);
965  m_current += size;
966 }
967 
968 uint32_t
970 {
971  NS_LOG_FUNCTION(this);
972  uint8_t byte0 = ReadU8();
973  uint8_t byte1 = ReadU8();
974  uint8_t byte2 = ReadU8();
975  uint8_t byte3 = ReadU8();
976  uint32_t data = byte3;
977  data <<= 8;
978  data |= byte2;
979  data <<= 8;
980  data |= byte1;
981  data <<= 8;
982  data |= byte0;
983  return data;
984 }
985 
986 uint64_t
988 {
989  NS_LOG_FUNCTION(this);
990  uint8_t byte0 = ReadU8();
991  uint8_t byte1 = ReadU8();
992  uint8_t byte2 = ReadU8();
993  uint8_t byte3 = ReadU8();
994  uint8_t byte4 = ReadU8();
995  uint8_t byte5 = ReadU8();
996  uint8_t byte6 = ReadU8();
997  uint8_t byte7 = ReadU8();
998  uint64_t data = byte7;
999  data <<= 8;
1000  data |= byte6;
1001  data <<= 8;
1002  data |= byte5;
1003  data <<= 8;
1004  data |= byte4;
1005  data <<= 8;
1006  data |= byte3;
1007  data <<= 8;
1008  data |= byte2;
1009  data <<= 8;
1010  data |= byte1;
1011  data <<= 8;
1012  data |= byte0;
1013 
1014  return data;
1015 }
1016 
1017 uint16_t
1019 {
1020  NS_LOG_FUNCTION(this);
1021  uint16_t retval = 0;
1022  retval |= ReadU8();
1023  retval <<= 8;
1024  retval |= ReadU8();
1025  return retval;
1026 }
1027 
1028 uint32_t
1030 {
1031  NS_LOG_FUNCTION(this);
1032  uint32_t retval = 0;
1033  retval |= ReadU8();
1034  retval <<= 8;
1035  retval |= ReadU8();
1036  retval <<= 8;
1037  retval |= ReadU8();
1038  retval <<= 8;
1039  retval |= ReadU8();
1040  return retval;
1041 }
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 
1066 uint16_t
1068 {
1069  NS_LOG_FUNCTION(this);
1070  uint8_t byte0 = ReadU8();
1071  uint8_t byte1 = ReadU8();
1072  uint16_t data = byte1;
1073  data <<= 8;
1074  data |= byte0;
1075  return data;
1076 }
1077 
1078 uint32_t
1080 {
1081  NS_LOG_FUNCTION(this);
1082  uint8_t byte0 = ReadU8();
1083  uint8_t byte1 = ReadU8();
1084  uint8_t byte2 = ReadU8();
1085  uint8_t byte3 = ReadU8();
1086  uint32_t data = byte3;
1087  data <<= 8;
1088  data |= byte2;
1089  data <<= 8;
1090  data |= byte1;
1091  data <<= 8;
1092  data |= byte0;
1093  return data;
1094 }
1095 
1096 uint64_t
1098 {
1099  NS_LOG_FUNCTION(this);
1100  uint8_t byte0 = ReadU8();
1101  uint8_t byte1 = ReadU8();
1102  uint8_t byte2 = ReadU8();
1103  uint8_t byte3 = ReadU8();
1104  uint8_t byte4 = ReadU8();
1105  uint8_t byte5 = ReadU8();
1106  uint8_t byte6 = ReadU8();
1107  uint8_t byte7 = ReadU8();
1108  uint64_t data = byte7;
1109  data <<= 8;
1110  data |= byte6;
1111  data <<= 8;
1112  data |= byte5;
1113  data <<= 8;
1114  data |= byte4;
1115  data <<= 8;
1116  data |= byte3;
1117  data <<= 8;
1118  data |= byte2;
1119  data <<= 8;
1120  data |= byte1;
1121  data <<= 8;
1122  data |= byte0;
1123 
1124  return data;
1125 }
1126 
1127 void
1128 Buffer::Iterator::Read(uint8_t* buffer, uint32_t size)
1129 {
1130  NS_LOG_FUNCTION(this << &buffer << size);
1131  for (uint32_t i = 0; i < size; i++)
1132  {
1133  buffer[i] = ReadU8();
1134  }
1135 }
1136 
1137 uint16_t
1139 {
1140  NS_LOG_FUNCTION(this << size);
1141  return CalculateIpChecksum(size, 0);
1142 }
1143 
1144 uint16_t
1145 Buffer::Iterator::CalculateIpChecksum(uint16_t size, uint32_t initialChecksum)
1146 {
1147  NS_LOG_FUNCTION(this << size << initialChecksum);
1148  /* see RFC 1071 to understand this code. */
1149  uint32_t sum = initialChecksum;
1150 
1151  for (int j = 0; j < size / 2; j++)
1152  {
1153  sum += ReadU16();
1154  }
1155 
1156  if (size & 1)
1157  {
1158  sum += ReadU8();
1159  }
1160 
1161  while (sum >> 16)
1162  {
1163  sum = (sum & 0xffff) + (sum >> 16);
1164  }
1165  return ~sum;
1166 }
1167 
1168 uint32_t
1170 {
1171  NS_LOG_FUNCTION(this);
1172  return m_dataEnd - m_dataStart;
1173 }
1174 
1175 uint32_t
1177 {
1178  NS_LOG_FUNCTION(this);
1179  return m_dataEnd - m_current;
1180 }
1181 
1182 std::string
1184 {
1185  NS_LOG_FUNCTION(this);
1186  std::string str = "You have attempted to read beyond the bounds of the "
1187  "available buffer space. This usually indicates that a "
1188  "Header::Deserialize or Trailer::Deserialize method "
1189  "is trying to read data which was not written by "
1190  "a Header::Serialize or Trailer::Serialize method. "
1191  "In short: check the code of your Serialize and Deserialize "
1192  "methods.";
1193  return str;
1194 }
1195 
1196 std::string
1198 {
1199  NS_LOG_FUNCTION(this);
1200  std::string str;
1201  if (m_current < m_dataStart)
1202  {
1203  str = "You have attempted to write before the start of the available "
1204  "buffer space. This usually indicates that Trailer::GetSerializedSize "
1205  "returned a size which is too small compared to what Trailer::Serialize "
1206  "is actually using.";
1207  }
1208  else if (m_current >= m_dataEnd)
1209  {
1210  str = "You have attempted to write after the end of the available "
1211  "buffer space. This usually indicates that Header::GetSerializedSize "
1212  "returned a size which is too small compared to what Header::Serialize "
1213  "is actually using.";
1214  }
1215  else
1216  {
1217  NS_ASSERT(m_current >= m_zeroStart && m_current < m_zeroEnd);
1218  str = "You have attempted to write inside the payload area of the "
1219  "buffer. This usually indicates that your Serialize method uses more "
1220  "buffer space than what your GetSerialized method returned.";
1221  }
1222  return str;
1223 }
1224 
1225 } // namespace ns3
#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: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:884
uint32_t GetRemainingSize() const
Definition: buffer.cc:1176
uint64_t ReadU64()
Definition: buffer.cc:987
void WriteU32(uint32_t data)
Definition: buffer.cc:871
void WriteHtonU64(uint64_t data)
Definition: buffer.cc:937
void WriteHtolsbU16(uint16_t data)
Definition: buffer.cc:905
uint64_t ReadNtohU64()
Definition: buffer.cc:1044
std::string GetReadErrorMessage() const
Returns an appropriate message indicating a read error.
Definition: buffer.cc:1183
uint16_t CalculateIpChecksum(uint16_t size)
Calculate the checksum.
Definition: buffer.cc:1138
void WriteU8(uint8_t data)
Definition: buffer.h:881
uint16_t SlowReadNtohU16()
Definition: buffer.cc:1018
uint8_t * m_data
a pointer to the underlying byte buffer.
Definition: buffer.h:485
void WriteHtolsbU32(uint32_t data)
Definition: buffer.cc:913
void Write(const uint8_t *buffer, uint32_t size)
Definition: buffer.cc:951
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:1067
bool Check(uint32_t i) const
Checks that the buffer position is not in the "virtual zero area".
Definition: buffer.cc:821
void WriteU16(uint16_t data)
Definition: buffer.cc:862
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:1029
void Read(uint8_t *buffer, uint32_t size)
Definition: buffer.cc:1128
uint64_t ReadLsbtohU64()
Definition: buffer.cc:1097
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:923
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:813
bool IsEnd() const
Definition: buffer.cc:799
bool IsStart() const
Definition: buffer.cc:806
uint32_t ReadU32()
Definition: buffer.cc:969
uint32_t GetDistanceFrom(const Iterator &o) const
Definition: buffer.cc:783
void Prev()
go backward by one byte
Definition: buffer.h:860
uint32_t GetSize() const
Definition: buffer.cc:1169
std::string GetWriteErrorMessage() const
Returns an appropriate message indicating a write error.
Definition: buffer.cc:1197
uint32_t ReadLsbtohU32()
Definition: buffer.cc:1079
automatically resized byte buffer
Definition: buffer.h:94
uint32_t GetSerializedSize() const
Return the number of bytes required for serialization.
Definition: buffer.cc:563
uint32_t GetInternalEnd() const
Get the buffer end position.
Definition: buffer.cc:304
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
Buffer CreateFragment(uint32_t start, uint32_t length) const
Definition: buffer.cc:526
static FreeList * g_freeList
Buffer data container.
Definition: buffer.h:806
static struct 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
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
std::vector< struct Buffer::Data * > FreeList
Container for buffer data.
Definition: buffer.h:797
static void Deallocate(struct Buffer::Data *data)
Deallocate the buffer memory.
Definition: buffer.cc:181
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
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:716
static struct Buffer::Data * Allocate(uint32_t reqSize)
Allocate a buffer data storage.
Definition: buffer.cc:164
void RemoveAtEnd(uint32_t end)
Definition: buffer.cc:490
void TransformIntoRealBuffer() const
Transform a "Virtual byte buffer" into a "Real byte buffer".
Definition: buffer.cc:696
uint32_t GetSize() const
Definition: buffer.h:1068
void AddAtStart(uint32_t start)
Definition: buffer.cc:311
uint32_t GetInternalSize() const
Get the buffer real size.
Definition: buffer.cc:297
Buffer::Iterator Begin() const
Definition: buffer.h:1074
void AddAtEnd(uint32_t end)
Definition: buffer.cc:357
Buffer::Iterator End() const
Definition: buffer.h:1081
Buffer & operator=(const Buffer &o)
Assignment operator.
Definition: buffer.cc:260
static void Recycle(struct Buffer::Data *data)
Recycle the buffer memory.
Definition: buffer.cc:101
struct Data * m_data
the buffer data storage
Definition: buffer.h:754
Buffer CreateFullCopy() const
Create a full copy of the buffer, including all the internal structures.
Definition: buffer.cc:538
bool CheckInternalState() const
Checks the internal buffer structures consistency.
Definition: buffer.cc:211
void Initialize(uint32_t zeroSize)
Initializes the buffer with a number of zeroes.
Definition: buffer.cc:245
uint32_t Deserialize(const uint8_t *buffer, uint32_t size)
Definition: buffer.cc:651
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:444
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:579
const uint8_t * PeekData() const
Definition: buffer.cc:706
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.
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
Local static destructor structure.
Definition: buffer.h:801