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 * 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
31namespace
32{
33
38struct 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
52namespace ns3
53{
54
56
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)
84Buffer::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
100void
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
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 }
143 NS_ASSERT(data->m_count == 1);
144 return data;
145}
146#else /* BUFFER_FREE_LIST */
147void
149{
151 NS_ASSERT(data->m_count == 0);
153}
154
155Buffer::Data*
157{
158 NS_LOG_FUNCTION(size);
159 return Allocate(size);
160}
161#endif /* BUFFER_FREE_LIST */
162
164
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
183void
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
199{
200 NS_LOG_FUNCTION(this << dataSize);
201 Initialize(dataSize);
202}
203
204Buffer::Buffer(uint32_t dataSize, bool initialize)
205{
206 NS_LOG_FUNCTION(this << dataSize << initialize);
207 if (initialize)
208 {
209 Initialize(dataSize);
210 }
211}
212
213bool
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 =
226 bool dirtyOk =
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
247void
249{
250 NS_LOG_FUNCTION(this << zeroSize);
255 m_zeroAreaEnd = m_zeroAreaStart + zeroSize;
260}
261
262Buffer&
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 {
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 {
296 }
297}
298
301{
302 NS_LOG_FUNCTION(this);
304}
305
308{
309 NS_LOG_FUNCTION(this);
311}
312
313void
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;
345 m_zeroAreaStart += 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
359void
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;
390 m_zeroAreaStart += delta;
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
405void
407{
408 NS_LOG_FUNCTION(this << &o);
409
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
446void
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);
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
492void
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
528Buffer
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
540Buffer
542{
543 NS_LOG_FUNCTION(this);
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
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
582Buffer::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
648Buffer::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
692void
694{
695 NS_LOG_FUNCTION(this);
697 Buffer tmp = CreateFullCopy();
698 *const_cast<Buffer*>(this) = tmp;
700}
701
702const uint8_t*
704{
705 NS_LOG_FUNCTION(this);
709 return m_data->m_data + m_start;
710}
711
712void
713Buffer::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
742Buffer::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
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
795bool
797{
798 NS_LOG_FUNCTION(this);
799 return m_current == m_dataEnd;
800}
801
802bool
804{
805 NS_LOG_FUNCTION(this);
806 return m_current == m_dataStart;
807}
808
809bool
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
817bool
819{
820 NS_LOG_FUNCTION(this << &i);
821 return i >= m_dataStart && !(i >= m_zeroStart && i < m_zeroEnd) && i <= m_dataEnd;
822}
823
824void
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
858void
860{
861 NS_LOG_FUNCTION(this << data);
862 WriteU8(data & 0xff);
863 data >>= 8;
864 WriteU8(data & 0xff);
865}
866
867void
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
880void
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
901void
903{
904 NS_LOG_FUNCTION(this << data);
905 WriteU8((data >> 0) & 0xff);
906 WriteU8((data >> 8) & 0xff);
907}
908
909void
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
919void
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
933void
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
947void
948Buffer::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
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
983uint64_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
1014uint16_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
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
1040uint64_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
1063uint16_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
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
1093uint64_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
1124void
1125Buffer::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
1134uint16_t
1136{
1137 NS_LOG_FUNCTION(this << size);
1138 return CalculateIpChecksum(size, 0);
1139}
1140
1141uint16_t
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
1167{
1168 NS_LOG_FUNCTION(this);
1169 return m_dataEnd - m_dataStart;
1170}
1171
1174{
1175 NS_LOG_FUNCTION(this);
1176 return m_dataEnd - m_current;
1177}
1178
1179std::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
1193std::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 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