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 (Buffer::FreeList::iterator 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 uint8_t* b = new uint8_t[size];
177 Buffer::Data* 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 uint8_t* 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 uint32_t* p = reinterpret_cast<uint32_t*>(buffer);
586 uint32_t size = 0;
587
588 // Add the zero data length
589 if (size + 4 <= maxSize)
590 {
591 size += 4;
593 }
594 else
595 {
596 return 0;
597 }
598
599 // Add the length of actual start data
600 uint32_t dataStartLength = m_zeroAreaStart - m_start;
601 if (size + 4 <= maxSize)
602 {
603 size += 4;
604 *p++ = dataStartLength;
605 }
606 else
607 {
608 return 0;
609 }
610
611 // Add the actual data
612 if (size + ((dataStartLength + 3) & (~3)) <= maxSize)
613 {
614 size += (dataStartLength + 3) & (~3);
615 memcpy(p, m_data->m_data + m_start, dataStartLength);
616 p += (((dataStartLength + 3) & (~3)) / 4); // Advance p, insuring 4 byte boundary
617 }
618 else
619 {
620 return 0;
621 }
622
623 // Add the length of the actual end data
624 uint32_t dataEndLength = m_end - m_zeroAreaEnd;
625 if (size + 4 <= maxSize)
626 {
627 size += 4;
628 *p++ = dataEndLength;
629 }
630 else
631 {
632 return 0;
633 }
634
635 // Add the actual data
636 if (size + ((dataEndLength + 3) & (~3)) <= maxSize)
637 {
638 // The following line is unnecessary.
639 // size += (dataEndLength + 3) & (~3);
640 memcpy(p, m_data->m_data + m_zeroAreaStart, dataEndLength);
641 // The following line is unnecessary.
642 // p += (((dataEndLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
643 }
644 else
645 {
646 return 0;
647 }
648
649 // Serialized everything successfully
650 return 1;
651}
652
654Buffer::Deserialize(const uint8_t* buffer, uint32_t size)
655{
656 NS_LOG_FUNCTION(this << &buffer << size);
657 const uint32_t* p = reinterpret_cast<const uint32_t*>(buffer);
658 uint32_t sizeCheck = size - 4;
659
660 NS_ASSERT(sizeCheck >= 4);
661 uint32_t zeroDataLength = *p++;
662 sizeCheck -= 4;
663
664 // Create zero bytes
665 Initialize(zeroDataLength);
666
667 // Add start data
668 NS_ASSERT(sizeCheck >= 4);
669 uint32_t dataStartLength = *p++;
670 sizeCheck -= 4;
671 AddAtStart(dataStartLength);
672
673 NS_ASSERT(sizeCheck >= dataStartLength);
674 Begin().Write(reinterpret_cast<uint8_t*>(const_cast<uint32_t*>(p)), dataStartLength);
675 p += (((dataStartLength + 3) & (~3)) / 4); // Advance p, insuring 4 byte boundary
676 sizeCheck -= ((dataStartLength + 3) & (~3));
677
678 // Add end data
679 NS_ASSERT(sizeCheck >= 4);
680 uint32_t dataEndLength = *p++;
681 sizeCheck -= 4;
682 AddAtEnd(dataEndLength);
683
684 NS_ASSERT(sizeCheck >= dataEndLength);
685 Buffer::Iterator tmp = End();
686 tmp.Prev(dataEndLength);
687 tmp.Write(reinterpret_cast<uint8_t*>(const_cast<uint32_t*>(p)), dataEndLength);
688 // The following line is unnecessary.
689 // p += (((dataEndLength+3)&(~3))/4); // Advance p, insuring 4 byte boundary
690 sizeCheck -= ((dataEndLength + 3) & (~3));
691
692 NS_ASSERT(sizeCheck == 0);
693 // return zero if buffer did not
694 // contain a complete message
695 return (sizeCheck != 0) ? 0 : 1;
696}
697
698void
700{
701 NS_LOG_FUNCTION(this);
703 Buffer tmp = CreateFullCopy();
704 *const_cast<Buffer*>(this) = tmp;
706}
707
708const uint8_t*
710{
711 NS_LOG_FUNCTION(this);
715 return m_data->m_data + m_start;
716}
717
718void
719Buffer::CopyData(std::ostream* os, uint32_t size) const
720{
721 NS_LOG_FUNCTION(this << &os << size);
722 if (size > 0)
723 {
724 uint32_t tmpsize = std::min(m_zeroAreaStart - m_start, size);
725 os->write((const char*)(m_data->m_data + m_start), tmpsize);
726 if (size > tmpsize)
727 {
728 size -= m_zeroAreaStart - m_start;
729 tmpsize = std::min(m_zeroAreaEnd - m_zeroAreaStart, size);
730 uint32_t left = tmpsize;
731 while (left > 0)
732 {
733 uint32_t toWrite = std::min(left, g_zeroes.size);
734 os->write(g_zeroes.buffer, toWrite);
735 left -= toWrite;
736 }
737 if (size > tmpsize)
738 {
739 size -= tmpsize;
740 tmpsize = std::min(m_end - m_zeroAreaEnd, size);
741 os->write((const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
742 }
743 }
744 }
745}
746
748Buffer::CopyData(uint8_t* buffer, uint32_t size) const
749{
750 NS_LOG_FUNCTION(this << &buffer << size);
751 uint32_t originalSize = size;
752 if (size > 0)
753 {
754 uint32_t tmpsize = std::min(m_zeroAreaStart - m_start, size);
755 memcpy(buffer, (const char*)(m_data->m_data + m_start), tmpsize);
756 buffer += tmpsize;
757 size -= tmpsize;
758 if (size > 0)
759 {
760 tmpsize = std::min(m_zeroAreaEnd - m_zeroAreaStart, size);
761 uint32_t left = tmpsize;
762 while (left > 0)
763 {
764 uint32_t toWrite = std::min(left, g_zeroes.size);
765 memcpy(buffer, g_zeroes.buffer, toWrite);
766 left -= toWrite;
767 buffer += toWrite;
768 }
769 size -= tmpsize;
770 if (size > 0)
771 {
772 tmpsize = std::min(m_end - m_zeroAreaEnd, size);
773 memcpy(buffer, (const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
774 size -= tmpsize;
775 }
776 }
777 }
778 return originalSize - size;
779}
780
781/******************************************************
782 * The buffer iterator below.
783 ******************************************************/
784
787{
788 NS_LOG_FUNCTION(this << &o);
789 NS_ASSERT(m_data == o.m_data);
790 int32_t diff = m_current - o.m_current;
791 if (diff < 0)
792 {
793 return -diff;
794 }
795 else
796 {
797 return diff;
798 }
799}
800
801bool
803{
804 NS_LOG_FUNCTION(this);
805 return m_current == m_dataEnd;
806}
807
808bool
810{
811 NS_LOG_FUNCTION(this);
812 return m_current == m_dataStart;
813}
814
815bool
817{
818 NS_LOG_FUNCTION(this << &start << &end);
819 return !(start < m_dataStart || end > m_dataEnd ||
820 (end > m_zeroStart && start < m_zeroEnd && m_zeroEnd != m_zeroStart && start != end));
821}
822
823bool
825{
826 NS_LOG_FUNCTION(this << &i);
827 return i >= m_dataStart && !(i >= m_zeroStart && i < m_zeroEnd) && i <= m_dataEnd;
828}
829
830void
832{
833 NS_LOG_FUNCTION(this << &start << &end);
834 NS_ASSERT(start.m_data == end.m_data);
835 NS_ASSERT(start.m_current <= end.m_current);
836 NS_ASSERT(start.m_zeroStart == end.m_zeroStart);
837 NS_ASSERT(start.m_zeroEnd == end.m_zeroEnd);
838 NS_ASSERT(m_data != start.m_data);
839 uint32_t size = end.m_current - start.m_current;
840 NS_ASSERT_MSG(CheckNoZero(m_current, m_current + size), GetWriteErrorMessage());
841 if (start.m_current <= start.m_zeroStart)
842 {
843 uint32_t toCopy = std::min(size, start.m_zeroStart - start.m_current);
844 memcpy(&m_data[m_current], &start.m_data[start.m_current], toCopy);
845 start.m_current += toCopy;
846 m_current += toCopy;
847 size -= toCopy;
848 }
849 if (start.m_current <= start.m_zeroEnd)
850 {
851 uint32_t toCopy = std::min(size, start.m_zeroEnd - start.m_current);
852 memset(&m_data[m_current], 0, toCopy);
853 start.m_current += toCopy;
854 m_current += toCopy;
855 size -= toCopy;
856 }
857 uint32_t toCopy = std::min(size, start.m_dataEnd - start.m_current);
858 uint8_t* from = &start.m_data[start.m_current - (start.m_zeroEnd - start.m_zeroStart)];
859 uint8_t* to = &m_data[m_current];
860 memcpy(to, from, toCopy);
861 m_current += toCopy;
862}
863
864void
866{
867 NS_LOG_FUNCTION(this << data);
868 WriteU8(data & 0xff);
869 data >>= 8;
870 WriteU8(data & 0xff);
871}
872
873void
875{
876 NS_LOG_FUNCTION(this << data);
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}
885
886void
888{
889 NS_LOG_FUNCTION(this << data);
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 data >>= 8;
900 WriteU8(data & 0xff);
901 data >>= 8;
902 WriteU8(data & 0xff);
903 data >>= 8;
904 WriteU8(data & 0xff);
905}
906
907void
909{
910 NS_LOG_FUNCTION(this << data);
911 WriteU8((data >> 0) & 0xff);
912 WriteU8((data >> 8) & 0xff);
913}
914
915void
917{
918 NS_LOG_FUNCTION(this << data);
919 WriteU8((data >> 0) & 0xff);
920 WriteU8((data >> 8) & 0xff);
921 WriteU8((data >> 16) & 0xff);
922 WriteU8((data >> 24) & 0xff);
923}
924
925void
927{
928 NS_LOG_FUNCTION(this << data);
929 WriteU8((data >> 0) & 0xff);
930 WriteU8((data >> 8) & 0xff);
931 WriteU8((data >> 16) & 0xff);
932 WriteU8((data >> 24) & 0xff);
933 WriteU8((data >> 32) & 0xff);
934 WriteU8((data >> 40) & 0xff);
935 WriteU8((data >> 48) & 0xff);
936 WriteU8((data >> 56) & 0xff);
937}
938
939void
941{
942 NS_LOG_FUNCTION(this << data);
943 WriteU8((data >> 56) & 0xff);
944 WriteU8((data >> 48) & 0xff);
945 WriteU8((data >> 40) & 0xff);
946 WriteU8((data >> 32) & 0xff);
947 WriteU8((data >> 24) & 0xff);
948 WriteU8((data >> 16) & 0xff);
949 WriteU8((data >> 8) & 0xff);
950 WriteU8((data >> 0) & 0xff);
951}
952
953void
954Buffer::Iterator::Write(const uint8_t* buffer, uint32_t size)
955{
956 NS_LOG_FUNCTION(this << &buffer << size);
957 NS_ASSERT_MSG(CheckNoZero(m_current, size), GetWriteErrorMessage());
958 uint8_t* to;
959 if (m_current <= m_zeroStart)
960 {
961 to = &m_data[m_current];
962 }
963 else
964 {
965 to = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
966 }
967 memcpy(to, buffer, size);
968 m_current += size;
969}
970
973{
974 NS_LOG_FUNCTION(this);
975 uint8_t byte0 = ReadU8();
976 uint8_t byte1 = ReadU8();
977 uint8_t byte2 = ReadU8();
978 uint8_t byte3 = ReadU8();
979 uint32_t data = byte3;
980 data <<= 8;
981 data |= byte2;
982 data <<= 8;
983 data |= byte1;
984 data <<= 8;
985 data |= byte0;
986 return data;
987}
988
989uint64_t
991{
992 NS_LOG_FUNCTION(this);
993 uint8_t byte0 = ReadU8();
994 uint8_t byte1 = ReadU8();
995 uint8_t byte2 = ReadU8();
996 uint8_t byte3 = ReadU8();
997 uint8_t byte4 = ReadU8();
998 uint8_t byte5 = ReadU8();
999 uint8_t byte6 = ReadU8();
1000 uint8_t byte7 = ReadU8();
1001 uint64_t data = byte7;
1002 data <<= 8;
1003 data |= byte6;
1004 data <<= 8;
1005 data |= byte5;
1006 data <<= 8;
1007 data |= byte4;
1008 data <<= 8;
1009 data |= byte3;
1010 data <<= 8;
1011 data |= byte2;
1012 data <<= 8;
1013 data |= byte1;
1014 data <<= 8;
1015 data |= byte0;
1016
1017 return data;
1018}
1019
1020uint16_t
1022{
1023 NS_LOG_FUNCTION(this);
1024 uint16_t retval = 0;
1025 retval |= ReadU8();
1026 retval <<= 8;
1027 retval |= ReadU8();
1028 return retval;
1029}
1030
1033{
1034 NS_LOG_FUNCTION(this);
1035 uint32_t retval = 0;
1036 retval |= ReadU8();
1037 retval <<= 8;
1038 retval |= ReadU8();
1039 retval <<= 8;
1040 retval |= ReadU8();
1041 retval <<= 8;
1042 retval |= ReadU8();
1043 return retval;
1044}
1045
1046uint64_t
1048{
1049 NS_LOG_FUNCTION(this);
1050 uint64_t retval = 0;
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 retval <<= 8;
1061 retval |= ReadU8();
1062 retval <<= 8;
1063 retval |= ReadU8();
1064 retval <<= 8;
1065 retval |= ReadU8();
1066 return retval;
1067}
1068
1069uint16_t
1071{
1072 NS_LOG_FUNCTION(this);
1073 uint8_t byte0 = ReadU8();
1074 uint8_t byte1 = ReadU8();
1075 uint16_t data = byte1;
1076 data <<= 8;
1077 data |= byte0;
1078 return data;
1079}
1080
1083{
1084 NS_LOG_FUNCTION(this);
1085 uint8_t byte0 = ReadU8();
1086 uint8_t byte1 = ReadU8();
1087 uint8_t byte2 = ReadU8();
1088 uint8_t byte3 = ReadU8();
1089 uint32_t data = byte3;
1090 data <<= 8;
1091 data |= byte2;
1092 data <<= 8;
1093 data |= byte1;
1094 data <<= 8;
1095 data |= byte0;
1096 return data;
1097}
1098
1099uint64_t
1101{
1102 NS_LOG_FUNCTION(this);
1103 uint8_t byte0 = ReadU8();
1104 uint8_t byte1 = ReadU8();
1105 uint8_t byte2 = ReadU8();
1106 uint8_t byte3 = ReadU8();
1107 uint8_t byte4 = ReadU8();
1108 uint8_t byte5 = ReadU8();
1109 uint8_t byte6 = ReadU8();
1110 uint8_t byte7 = ReadU8();
1111 uint64_t data = byte7;
1112 data <<= 8;
1113 data |= byte6;
1114 data <<= 8;
1115 data |= byte5;
1116 data <<= 8;
1117 data |= byte4;
1118 data <<= 8;
1119 data |= byte3;
1120 data <<= 8;
1121 data |= byte2;
1122 data <<= 8;
1123 data |= byte1;
1124 data <<= 8;
1125 data |= byte0;
1126
1127 return data;
1128}
1129
1130void
1131Buffer::Iterator::Read(uint8_t* buffer, uint32_t size)
1132{
1133 NS_LOG_FUNCTION(this << &buffer << size);
1134 for (uint32_t i = 0; i < size; i++)
1135 {
1136 buffer[i] = ReadU8();
1137 }
1138}
1139
1140uint16_t
1142{
1143 NS_LOG_FUNCTION(this << size);
1144 return CalculateIpChecksum(size, 0);
1145}
1146
1147uint16_t
1149{
1150 NS_LOG_FUNCTION(this << size << initialChecksum);
1151 /* see RFC 1071 to understand this code. */
1152 uint32_t sum = initialChecksum;
1153
1154 for (int j = 0; j < size / 2; j++)
1155 {
1156 sum += ReadU16();
1157 }
1158
1159 if (size & 1)
1160 {
1161 sum += ReadU8();
1162 }
1163
1164 while (sum >> 16)
1165 {
1166 sum = (sum & 0xffff) + (sum >> 16);
1167 }
1168 return ~sum;
1169}
1170
1173{
1174 NS_LOG_FUNCTION(this);
1175 return m_dataEnd - m_dataStart;
1176}
1177
1180{
1181 NS_LOG_FUNCTION(this);
1182 return m_dataEnd - m_current;
1183}
1184
1185std::string
1187{
1188 NS_LOG_FUNCTION(this);
1189 std::string str = "You have attempted to read beyond the bounds of the "
1190 "available buffer space. This usually indicates that a "
1191 "Header::Deserialize or Trailer::Deserialize method "
1192 "is trying to read data which was not written by "
1193 "a Header::Serialize or Trailer::Serialize method. "
1194 "In short: check the code of your Serialize and Deserialize "
1195 "methods.";
1196 return str;
1197}
1198
1199std::string
1201{
1202 NS_LOG_FUNCTION(this);
1203 std::string str;
1204 if (m_current < m_dataStart)
1205 {
1206 str = "You have attempted to write before the start of the available "
1207 "buffer space. This usually indicates that Trailer::GetSerializedSize "
1208 "returned a size which is too small compared to what Trailer::Serialize "
1209 "is actually using.";
1210 }
1211 else if (m_current >= m_dataEnd)
1212 {
1213 str = "You have attempted to write after the end of the available "
1214 "buffer space. This usually indicates that Header::GetSerializedSize "
1215 "returned a size which is too small compared to what Header::Serialize "
1216 "is actually using.";
1217 }
1218 else
1219 {
1220 NS_ASSERT(m_current >= m_zeroStart && m_current < m_zeroEnd);
1221 str = "You have attempted to write inside the payload area of the "
1222 "buffer. This usually indicates that your Serialize method uses more "
1223 "buffer space than what your GetSerialized method returned.";
1224 }
1225 return str;
1226}
1227
1228} // 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:887
uint32_t GetRemainingSize() const
Definition: buffer.cc:1179
uint64_t ReadU64()
Definition: buffer.cc:990
void WriteU32(uint32_t data)
Definition: buffer.cc:874
void WriteHtonU64(uint64_t data)
Definition: buffer.cc:940
void WriteHtolsbU16(uint16_t data)
Definition: buffer.cc:908
uint64_t ReadNtohU64()
Definition: buffer.cc:1047
std::string GetReadErrorMessage() const
Returns an appropriate message indicating a read error.
Definition: buffer.cc:1186
uint16_t CalculateIpChecksum(uint16_t size)
Calculate the checksum.
Definition: buffer.cc:1141
void WriteU8(uint8_t data)
Definition: buffer.h:881
uint16_t SlowReadNtohU16()
Definition: buffer.cc:1021
uint8_t * m_data
a pointer to the underlying byte buffer.
Definition: buffer.h:485
void WriteHtolsbU32(uint32_t data)
Definition: buffer.cc:916
void Write(const uint8_t *buffer, uint32_t size)
Definition: buffer.cc:954
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:1070
bool Check(uint32_t i) const
Checks that the buffer position is not in the "virtual zero area".
Definition: buffer.cc:824
void WriteU16(uint16_t data)
Definition: buffer.cc:865
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:1032
void Read(uint8_t *buffer, uint32_t size)
Definition: buffer.cc:1131
uint64_t ReadLsbtohU64()
Definition: buffer.cc:1100
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:926
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:816
bool IsEnd() const
Definition: buffer.cc:802
bool IsStart() const
Definition: buffer.cc:809
uint32_t ReadU32()
Definition: buffer.cc:972
uint32_t GetDistanceFrom(const Iterator &o) const
Definition: buffer.cc:786
void Prev()
go backward by one byte
Definition: buffer.h:860
uint32_t GetSize() const
Definition: buffer.cc:1172
std::string GetWriteErrorMessage() const
Returns an appropriate message indicating a write error.
Definition: buffer.cc:1200
uint32_t ReadLsbtohU32()
Definition: buffer.cc:1082
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:719
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:699
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:654
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:709
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