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