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