A Discrete-Event Network Simulator
API
buffer.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2005,2006,2007 INRIA
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 */
20#include "buffer.h"
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<<", zero start="<<m_zeroAreaStart<< \
26 ", zero end="<<m_zeroAreaEnd<<", count="<<m_data->m_count<<", size="<<m_data->m_size<< \
27 ", dirty start="<<m_data->m_dirtyStart<<", dirty end="<<m_data->m_dirtyEnd)
28
29namespace {
30
35static struct Zeroes
36{
38 : size (1000)
39 {
40 memset (buffer, 0, size);
41 }
42 char buffer[1000];
43 const uint32_t size;
45
46}
47
48namespace ns3 {
49
51
52
54#ifdef BUFFER_FREE_LIST
55/* The following macros are pretty evil but they are needed to allow us to
56 * keep track of 3 possible states for the g_freeList variable:
57 * - uninitialized means that no one has created a buffer yet
58 * so no one has created the associated free list (it is created
59 * on-demand when the first buffer is created)
60 * - initialized means that the free list exists and is valid
61 * - destroyed means that the static destructors of this compilation unit
62 * have run so, the free list has been cleared from its content
63 * The key is that in destroyed state, we are careful not re-create it
64 * which is a typical weakness of lazy evaluation schemes which use
65 * '0' as a special value to indicate both un-initialized and destroyed.
66 * Note that it is important to use '0' as the marker for un-initialized state
67 * because the variable holding this state information is initialized to zero
68 * which the compiler assigns to zero-memory which is initialized to _zero_
69 * before the constructors run so this ensures perfect handling of crazy
70 * constructor orderings.
71 */
72#define MAGIC_DESTROYED (~(long) 0)
73#define IS_UNINITIALIZED(x) (x == (Buffer::FreeList*)0)
74#define IS_DESTROYED(x) (x == (Buffer::FreeList*)MAGIC_DESTROYED)
75#define IS_INITIALIZED(x) (!IS_UNINITIALIZED (x) && !IS_DESTROYED (x))
76#define DESTROYED ((Buffer::FreeList*)MAGIC_DESTROYED)
77#define UNINITIALIZED ((Buffer::FreeList*)0)
80struct Buffer::LocalStaticDestructor Buffer::g_localStaticDestructor;
81
83{
84 NS_LOG_FUNCTION (this);
86 {
87 for (Buffer::FreeList::iterator i = g_freeList->begin ();
88 i != g_freeList->end (); i++)
89 {
91 }
92 delete g_freeList;
94 }
95}
96
97void
99{
101 NS_ASSERT (data->m_count == 0);
103 g_maxSize = std::max (g_maxSize, data->m_size);
104 /* feed into free list */
105 if (data->m_size < g_maxSize ||
107 g_freeList->size () > 1000)
108 {
110 }
111 else
112 {
114 g_freeList->push_back (data);
115 }
116}
117
120{
121 NS_LOG_FUNCTION (dataSize);
122 /* try to find a buffer correctly sized. */
124 {
126 }
127 else if (IS_INITIALIZED (g_freeList))
128 {
129 while (!g_freeList->empty ())
130 {
131 struct Buffer::Data *data = g_freeList->back ();
132 g_freeList->pop_back ();
133 if (data->m_size >= dataSize)
134 {
135 data->m_count = 1;
136 return data;
137 }
139 }
140 }
141 struct Buffer::Data *data = Buffer::Allocate (dataSize);
142 NS_ASSERT (data->m_count == 1);
143 return data;
144}
145#else /* BUFFER_FREE_LIST */
146void
148{
150 NS_ASSERT (data->m_count == 0);
152}
153
154Buffer::Data *
156{
157 NS_LOG_FUNCTION (size);
158 return Allocate (size);
159}
160#endif /* BUFFER_FREE_LIST */
161
162struct Buffer::Data *
164{
165 NS_LOG_FUNCTION (reqSize);
166 if (reqSize == 0)
167 {
168 reqSize = 1;
169 }
170 NS_ASSERT (reqSize >= 1);
171 uint32_t size = reqSize - 1 + sizeof (struct Buffer::Data);
172 uint8_t *b = new uint8_t [size];
173 struct Buffer::Data *data = reinterpret_cast<struct Buffer::Data*>(b);
174 data->m_size = reqSize;
175 data->m_count = 1;
176 return data;
177}
178
179void
181{
183 NS_ASSERT (data->m_count == 0);
184 uint8_t *buf = reinterpret_cast<uint8_t *> (data);
185 delete [] buf;
186}
187
189{
190 NS_LOG_FUNCTION (this);
191 Initialize (0);
192}
193
195{
196 NS_LOG_FUNCTION (this << dataSize);
197 Initialize (dataSize);
198}
199
200Buffer::Buffer (uint32_t dataSize, bool initialize)
201{
202 NS_LOG_FUNCTION (this << dataSize << initialize);
203 if (initialize == true)
204 {
205 Initialize (dataSize);
206 }
207}
208
209bool
211{
212 NS_LOG_FUNCTION (this);
213#if 0
214 // If you want to modify any code in this file, enable this checking code.
215 // Otherwise, there is not much point is enabling it because the
216 // current implementation has been fairly seriously tested and the cost
217 // of this constant checking is pretty high, even for a debug build.
218 bool offsetsOk =
222 bool dirtyOk =
225 bool internalSizeOk = m_end - (m_zeroAreaEnd - m_zeroAreaStart) <= m_data->m_size &&
226 m_start <= m_data->m_size &&
227 m_zeroAreaStart <= m_data->m_size;
228
229 bool ok = m_data->m_count > 0 && offsetsOk && dirtyOk && internalSizeOk;
230 if (!ok)
231 {
232 LOG_INTERNAL_STATE ("check " << this <<
233 ", " << (offsetsOk ? "true" : "false") <<
234 ", " << (dirtyOk ? "true" : "false") <<
235 ", " << (internalSizeOk ? "true" : "false") << " ");
236 }
237 return ok;
238#else
239 return true;
240#endif
241}
242
243void
245{
246 NS_LOG_FUNCTION (this << zeroSize);
251 m_zeroAreaEnd = m_zeroAreaStart + zeroSize;
256}
257
258Buffer &
260{
262 if (m_data != o.m_data)
263 {
264 // not assignment to self.
265 m_data->m_count--;
266 if (m_data->m_count == 0)
267 {
268 Recycle (m_data);
269 }
270 m_data = o.m_data;
271 m_data->m_count++;
272 }
277 m_start = o.m_start;
278 m_end = o.m_end;
280 return *this;
281}
282
284{
285 NS_LOG_FUNCTION (this);
288 m_data->m_count--;
289 if (m_data->m_count == 0)
290 {
291 Recycle (m_data);
292 }
293}
294
297{
298 NS_LOG_FUNCTION (this);
300}
303{
304 NS_LOG_FUNCTION (this);
306}
307
308void
310{
311 NS_LOG_FUNCTION (this << start);
313 bool isDirty = m_data->m_count > 1 && m_start > m_data->m_dirtyStart;
314 if (m_start >= start && !isDirty)
315 {
316 /* enough space in the buffer and not dirty.
317 * To add: |..|
318 * Before: |*****---------***|
319 * After: |***..---------***|
320 */
322 m_start -= start;
323 // update dirty area
325 }
326 else
327 {
328 uint32_t newSize = GetInternalSize () + start;
329 struct Buffer::Data *newData = Buffer::Create (newSize);
330 memcpy (newData->m_data + start, m_data->m_data + m_start, GetInternalSize ());
331 m_data->m_count--;
332 if (m_data->m_count == 0)
333 {
335 }
336 m_data = newData;
337
338 int32_t delta = start - m_start;
339 m_start += delta;
340 m_zeroAreaStart += delta;
341 m_zeroAreaEnd += delta;
342 m_end += delta;
343 m_start -= start;
344
345 // update dirty area
348 }
350 LOG_INTERNAL_STATE ("add start=" << start << ", ");
352}
353void
355{
356 NS_LOG_FUNCTION (this << end);
358 bool isDirty = m_data->m_count > 1 && m_end < m_data->m_dirtyEnd;
359 if (GetInternalEnd () + end <= m_data->m_size && !isDirty)
360 {
361 /* enough space in buffer and not dirty
362 * Add: |...|
363 * Before: |**----*****|
364 * After: |**----...**|
365 */
367 m_end += end;
368 // update dirty area.
370 }
371 else
372 {
373 uint32_t newSize = GetInternalSize () + end;
374 struct Buffer::Data *newData = Buffer::Create (newSize);
375 memcpy (newData->m_data, m_data->m_data + m_start, GetInternalSize ());
376 m_data->m_count--;
377 if (m_data->m_count == 0)
378 {
380 }
381 m_data = newData;
382
383 int32_t delta = -m_start;
384 m_zeroAreaStart += delta;
385 m_zeroAreaEnd += delta;
386 m_end += delta;
387 m_start += delta;
388 m_end += end;
389
390 // update dirty area
393 }
395 LOG_INTERNAL_STATE ("add end=" << end << ", ");
397}
398
399void
401{
402 NS_LOG_FUNCTION (this << &o);
403
404 if (m_data->m_count == 1 &&
406 m_end == m_data->m_dirtyEnd &&
407 o.m_start == o.m_zeroAreaStart &&
409 {
416 {
418 }
419 uint32_t zeroSize = o.m_zeroAreaEnd - o.m_zeroAreaStart;
420 m_zeroAreaEnd = m_end + zeroSize;
423 uint32_t endData = o.m_end - o.m_zeroAreaEnd;
424 AddAtEnd (endData);
425 Buffer::Iterator dst = End ();
426 dst.Prev (endData);
427 Buffer::Iterator src = o.End ();
428 src.Prev (endData);
429 dst.Write (src, o.End ());
431 return;
432 }
433
434 *this = CreateFullCopy ();
435 AddAtEnd (o.GetSize ());
436 Buffer::Iterator destStart = End ();
437 destStart.Prev (o.GetSize ());
438 destStart.Write (o.Begin (), o.End ());
440}
441
442void
444{
445 NS_LOG_FUNCTION (this << start);
447 uint32_t newStart = m_start + start;
448 if (newStart <= m_zeroAreaStart)
449 {
450 /* only remove start of buffer
451 */
452 m_start = newStart;
453 }
454 else if (newStart <= m_zeroAreaEnd)
455 {
456 /* remove start of buffer _and_ start of zero area
457 */
458 uint32_t delta = newStart - m_zeroAreaStart;
460 m_zeroAreaEnd -= delta;
461 m_end -= delta;
462 }
463 else if (newStart <= m_end)
464 {
465 /* remove start of buffer, complete zero area, and part
466 * of end of buffer
467 */
468 NS_ASSERT (m_end >= start);
470 m_start = newStart - zeroSize;
471 m_end -= zeroSize;
474 }
475 else
476 {
477 /* remove all buffer */
479 m_start = m_end;
482 }
484 LOG_INTERNAL_STATE ("rem start=" << start << ", ");
486}
487void
489{
490 NS_LOG_FUNCTION (this << end);
492 uint32_t newEnd = m_end - std::min (end, m_end - m_start);
493 if (newEnd > m_zeroAreaEnd)
494 {
495 /* remove part of end of buffer */
496 m_end = newEnd;
497 }
498 else if (newEnd > m_zeroAreaStart)
499 {
500 /* remove end of buffer, part of zero area */
501 m_end = newEnd;
502 m_zeroAreaEnd = newEnd;
503 }
504 else if (newEnd > m_start)
505 {
506 /* remove end of buffer, zero area, part of start of buffer */
507 m_end = newEnd;
508 m_zeroAreaEnd = newEnd;
509 m_zeroAreaStart = newEnd;
510 }
511 else
512 {
513 /* remove all buffer */
514 m_end = m_start;
517 }
519 LOG_INTERNAL_STATE ("rem end=" << end << ", ");
521}
522
523Buffer
525{
526 NS_LOG_FUNCTION (this << start << length);
528 Buffer tmp = *this;
529 tmp.RemoveAtStart (start);
530 tmp.RemoveAtEnd (GetSize () - (start + length));
532 return tmp;
533}
534
535Buffer
537{
538 NS_LOG_FUNCTION (this);
540 if (m_zeroAreaEnd - m_zeroAreaStart != 0)
541 {
542 Buffer tmp;
545 uint32_t dataStart = m_zeroAreaStart - m_start;
546 tmp.AddAtStart (dataStart);
547 tmp.Begin ().Write (m_data->m_data+m_start, dataStart);
548 uint32_t dataEnd = m_end - m_zeroAreaEnd;
549 tmp.AddAtEnd (dataEnd);
550 Buffer::Iterator i = tmp.End ();
551 i.Prev (dataEnd);
552 i.Write (m_data->m_data+m_zeroAreaStart,dataEnd);
554 return tmp;
555 }
557 return *this;
558}
559
562{
563 NS_LOG_FUNCTION (this);
564 uint32_t dataStart = (m_zeroAreaStart - m_start + 3) & (~0x3);
565 uint32_t dataEnd = (m_end - m_zeroAreaEnd + 3) & (~0x3);
566
567 // total size 4-bytes for dataStart length
568 // + X number of bytes for dataStart
569 // + 4-bytes for dataEnd length
570 // + X number of bytes for dataEnd
571 uint32_t sz = sizeof (uint32_t)
572 + sizeof (uint32_t)
573 + dataStart
574 + sizeof (uint32_t)
575 + dataEnd;
576
577 return sz;
578}
579
581Buffer::Serialize (uint8_t* buffer, uint32_t maxSize) const
582{
583 NS_LOG_FUNCTION (this << &buffer << maxSize);
584 uint32_t* p = reinterpret_cast<uint32_t *> (buffer);
585 uint32_t size = 0;
586
587 // Add the zero data length
588 if (size + 4 <= maxSize)
589 {
590 size += 4;
592 }
593 else
594 {
595 return 0;
596 }
597
598 // Add the length of actual start data
599 uint32_t dataStartLength = m_zeroAreaStart - m_start;
600 if (size + 4 <= maxSize)
601 {
602 size += 4;
603 *p++ = dataStartLength;
604 }
605 else
606 {
607 return 0;
608 }
609
610 // Add the actual data
611 if (size + ((dataStartLength + 3) & (~3)) <= maxSize)
612 {
613 size += (dataStartLength + 3) & (~3);
614 memcpy (p, m_data->m_data + m_start, dataStartLength);
615 p += (((dataStartLength + 3) & (~3))/4); // Advance p, insuring 4 byte boundary
616 }
617 else
618 {
619 return 0;
620 }
621
622 // Add the length of the actual end data
623 uint32_t dataEndLength = m_end - m_zeroAreaEnd;
624 if (size + 4 <= maxSize)
625 {
626 size += 4;
627 *p++ = dataEndLength;
628 }
629 else
630 {
631 return 0;
632 }
633
634 // Add the actual data
635 if (size + ((dataEndLength + 3) & (~3)) <= maxSize)
636 {
637 // The following line is unnecessary.
638 // size += (dataEndLength + 3) & (~3);
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 else
644 {
645 return 0;
646 }
647
648 // Serialized everything successfully
649 return 1;
650}
651
653Buffer::Deserialize (const uint8_t *buffer, uint32_t size)
654{
655 NS_LOG_FUNCTION (this << &buffer << size);
656 const uint32_t* p = reinterpret_cast<const uint32_t *> (buffer);
657 uint32_t sizeCheck = size-4;
658
659 NS_ASSERT (sizeCheck >= 4);
660 uint32_t zeroDataLength = *p++;
661 sizeCheck -= 4;
662
663 // Create zero bytes
664 Initialize (zeroDataLength);
665
666 // Add start data
667 NS_ASSERT (sizeCheck >= 4);
668 uint32_t dataStartLength = *p++;
669 sizeCheck -= 4;
670 AddAtStart (dataStartLength);
671
672 NS_ASSERT (sizeCheck >= dataStartLength);
673 Begin ().Write (reinterpret_cast<uint8_t *> (const_cast<uint32_t *> (p)), dataStartLength);
674 p += (((dataStartLength+3)&(~3))/4); // Advance p, insuring 4 byte boundary
675 sizeCheck -= ((dataStartLength+3)&(~3));
676
677 // Add end data
678 NS_ASSERT (sizeCheck >= 4);
679 uint32_t dataEndLength = *p++;
680 sizeCheck -= 4;
681 AddAtEnd (dataEndLength);
682
683 NS_ASSERT (sizeCheck >= dataEndLength);
684 Buffer::Iterator tmp = End ();
685 tmp.Prev (dataEndLength);
686 tmp.Write (reinterpret_cast<uint8_t *> (const_cast<uint32_t *> (p)), dataEndLength);
687 // The following line is unnecessary.
688 // p += (((dataEndLength+3)&(~3))/4); // Advance p, insuring 4 byte boundary
689 sizeCheck -= ((dataEndLength+3)&(~3));
690
691 NS_ASSERT (sizeCheck == 0);
692 // return zero if buffer did not
693 // contain a complete message
694 return (sizeCheck != 0) ? 0 : 1;
695}
696
697
698void
700{
701 NS_LOG_FUNCTION (this);
703 Buffer tmp = CreateFullCopy ();
704 *const_cast<Buffer *> (this) = tmp;
706}
707
708
709uint8_t const*
711{
712 NS_LOG_FUNCTION (this);
716 return m_data->m_data + m_start;
717}
718
719void
720Buffer::CopyData (std::ostream *os, uint32_t size) const
721{
722 NS_LOG_FUNCTION (this << &os << size);
723 if (size > 0)
724 {
725 uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size);
726 os->write ((const char*)(m_data->m_data + m_start), tmpsize);
727 if (size > tmpsize)
728 {
729 size -= m_zeroAreaStart-m_start;
730 tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size);
731 uint32_t left = tmpsize;
732 while (left > 0)
733 {
734 uint32_t toWrite = std::min (left, g_zeroes.size);
735 os->write (g_zeroes.buffer, toWrite);
736 left -= toWrite;
737 }
738 if (size > tmpsize)
739 {
740 size -= tmpsize;
741 tmpsize = std::min (m_end - m_zeroAreaEnd, size);
742 os->write ((const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
743 }
744 }
745 }
746}
747
749Buffer::CopyData (uint8_t *buffer, uint32_t size) const
750{
751 NS_LOG_FUNCTION (this << &buffer << size);
752 uint32_t originalSize = size;
753 if (size > 0)
754 {
755 uint32_t tmpsize = std::min (m_zeroAreaStart-m_start, size);
756 memcpy (buffer, (const char*)(m_data->m_data + m_start), tmpsize);
757 buffer += tmpsize;
758 size -= tmpsize;
759 if (size > 0)
760 {
761 tmpsize = std::min (m_zeroAreaEnd - m_zeroAreaStart, size);
762 uint32_t left = tmpsize;
763 while (left > 0)
764 {
765 uint32_t toWrite = std::min (left, g_zeroes.size);
766 memcpy (buffer, g_zeroes.buffer, toWrite);
767 left -= toWrite;
768 buffer += toWrite;
769 }
770 size -= tmpsize;
771 if (size > 0)
772 {
773 tmpsize = std::min (m_end - m_zeroAreaEnd, size);
774 memcpy (buffer, (const char*)(m_data->m_data + m_zeroAreaStart), tmpsize);
775 size -= tmpsize;
776 }
777 }
778 }
779 return originalSize - size;
780}
781
782/******************************************************
783 * The buffer iterator below.
784 ******************************************************/
785
786
789{
790 NS_LOG_FUNCTION (this << &o);
791 NS_ASSERT (m_data == o.m_data);
792 int32_t diff = m_current - o.m_current;
793 if (diff < 0)
794 {
795 return -diff;
796 }
797 else
798 {
799 return diff;
800 }
801}
802
803bool
805{
806 NS_LOG_FUNCTION (this);
807 return m_current == m_dataEnd;
808}
809bool
811{
812 NS_LOG_FUNCTION (this);
813 return m_current == m_dataStart;
814}
815
816bool
818{
819 NS_LOG_FUNCTION (this << &start << &end);
820 return !(start < m_dataStart ||
821 end > m_dataEnd ||
822 (end > m_zeroStart && start < m_zeroEnd && m_zeroEnd != m_zeroStart && start != end)
823 );
824}
825bool
827{
828 NS_LOG_FUNCTION (this << &i);
829 return i >= m_dataStart &&
830 !(i >= m_zeroStart && i < m_zeroEnd) &&
831 i <= m_dataEnd;
832}
833
834
835void
837{
838 NS_LOG_FUNCTION (this << &start << &end);
839 NS_ASSERT (start.m_data == end.m_data);
840 NS_ASSERT (start.m_current <= end.m_current);
841 NS_ASSERT (start.m_zeroStart == end.m_zeroStart);
842 NS_ASSERT (start.m_zeroEnd == end.m_zeroEnd);
843 NS_ASSERT (m_data != start.m_data);
844 uint32_t size = end.m_current - start.m_current;
845 NS_ASSERT_MSG (CheckNoZero (m_current, m_current + size),
846 GetWriteErrorMessage ());
847 if (start.m_current <= start.m_zeroStart)
848 {
849 uint32_t toCopy = std::min (size, start.m_zeroStart - start.m_current);
850 memcpy (&m_data[m_current], &start.m_data[start.m_current], toCopy);
851 start.m_current += toCopy;
852 m_current += toCopy;
853 size -= toCopy;
854 }
855 if (start.m_current <= start.m_zeroEnd)
856 {
857 uint32_t toCopy = std::min (size, start.m_zeroEnd - start.m_current);
858 memset (&m_data[m_current], 0, toCopy);
859 start.m_current += toCopy;
860 m_current += toCopy;
861 size -= toCopy;
862 }
863 uint32_t toCopy = std::min (size, start.m_dataEnd - start.m_current);
864 uint8_t *from = &start.m_data[start.m_current - (start.m_zeroEnd-start.m_zeroStart)];
865 uint8_t *to = &m_data[m_current];
866 memcpy (to, from, toCopy);
867 m_current += toCopy;
868}
869
870void
872{
873 NS_LOG_FUNCTION (this << data);
874 WriteU8 (data & 0xff);
875 data >>= 8;
876 WriteU8 (data & 0xff);
877}
878void
880{
881 NS_LOG_FUNCTION (this << data);
882 WriteU8 (data & 0xff);
883 data >>= 8;
884 WriteU8 (data & 0xff);
885 data >>= 8;
886 WriteU8 (data & 0xff);
887 data >>= 8;
888 WriteU8 (data & 0xff);
889}
890void
892{
893 NS_LOG_FUNCTION (this << data);
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 data >>= 8;
906 WriteU8 (data & 0xff);
907 data >>= 8;
908 WriteU8 (data & 0xff);
909}
910void
912{
913 NS_LOG_FUNCTION (this << data);
914 WriteU8 ((data >> 0) & 0xff);
915 WriteU8 ((data >> 8) & 0xff);
916}
917void
919{
920 NS_LOG_FUNCTION (this << data);
921 WriteU8 ((data >> 0) & 0xff);
922 WriteU8 ((data >> 8) & 0xff);
923 WriteU8 ((data >> 16) & 0xff);
924 WriteU8 ((data >> 24) & 0xff);
925}
926void
928{
929 NS_LOG_FUNCTION (this << data);
930 WriteU8 ((data >> 0) & 0xff);
931 WriteU8 ((data >> 8) & 0xff);
932 WriteU8 ((data >> 16) & 0xff);
933 WriteU8 ((data >> 24) & 0xff);
934 WriteU8 ((data >> 32) & 0xff);
935 WriteU8 ((data >> 40) & 0xff);
936 WriteU8 ((data >> 48) & 0xff);
937 WriteU8 ((data >> 56) & 0xff);
938}
939
940void
942{
943 NS_LOG_FUNCTION (this << data);
944 WriteU8 ((data >> 56) & 0xff);
945 WriteU8 ((data >> 48) & 0xff);
946 WriteU8 ((data >> 40) & 0xff);
947 WriteU8 ((data >> 32) & 0xff);
948 WriteU8 ((data >> 24) & 0xff);
949 WriteU8 ((data >> 16) & 0xff);
950 WriteU8 ((data >> 8) & 0xff);
951 WriteU8 ((data >> 0) & 0xff);
952}
953void
954Buffer::Iterator::Write (uint8_t const*buffer, uint32_t size)
955{
956 NS_LOG_FUNCTION (this << &buffer << size);
957 NS_ASSERT_MSG (CheckNoZero (m_current, size),
958 GetWriteErrorMessage ());
959 uint8_t *to;
960 if (m_current <= m_zeroStart)
961 {
962 to = &m_data[m_current];
963 }
964 else
965 {
966 to = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
967 }
968 memcpy (to, buffer, size);
969 m_current += size;
970}
971
974{
975 NS_LOG_FUNCTION (this);
976 uint8_t byte0 = ReadU8 ();
977 uint8_t byte1 = ReadU8 ();
978 uint8_t byte2 = ReadU8 ();
979 uint8_t byte3 = ReadU8 ();
980 uint32_t data = byte3;
981 data <<= 8;
982 data |= byte2;
983 data <<= 8;
984 data |= byte1;
985 data <<= 8;
986 data |= byte0;
987 return data;
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}
1019uint16_t
1021{
1022 NS_LOG_FUNCTION (this);
1023 uint16_t retval = 0;
1024 retval |= ReadU8 ();
1025 retval <<= 8;
1026 retval |= ReadU8 ();
1027 return retval;
1028}
1029uint32_t
1031{
1032 NS_LOG_FUNCTION (this);
1033 uint32_t retval = 0;
1034 retval |= ReadU8 ();
1035 retval <<= 8;
1036 retval |= ReadU8 ();
1037 retval <<= 8;
1038 retval |= ReadU8 ();
1039 retval <<= 8;
1040 retval |= ReadU8 ();
1041 return retval;
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}
1065uint16_t
1067{
1068 NS_LOG_FUNCTION (this);
1069 uint8_t byte0 = ReadU8 ();
1070 uint8_t byte1 = ReadU8 ();
1071 uint16_t data = byte1;
1072 data <<= 8;
1073 data |= byte0;
1074 return data;
1075}
1076uint32_t
1078{
1079 NS_LOG_FUNCTION (this);
1080 uint8_t byte0 = ReadU8 ();
1081 uint8_t byte1 = ReadU8 ();
1082 uint8_t byte2 = ReadU8 ();
1083 uint8_t byte3 = ReadU8 ();
1084 uint32_t data = byte3;
1085 data <<= 8;
1086 data |= byte2;
1087 data <<= 8;
1088 data |= byte1;
1089 data <<= 8;
1090 data |= byte0;
1091 return data;
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}
1123void
1124Buffer::Iterator::Read (uint8_t *buffer, uint32_t size)
1125{
1126 NS_LOG_FUNCTION (this << &buffer << size);
1127 for (uint32_t i = 0; i < size; i++)
1128 {
1129 buffer[i] = ReadU8 ();
1130 }
1131}
1132
1133uint16_t
1135{
1136 NS_LOG_FUNCTION (this << size);
1137 return CalculateIpChecksum (size, 0);
1138}
1139
1140uint16_t
1141Buffer::Iterator::CalculateIpChecksum (uint16_t size, uint32_t initialChecksum)
1142{
1143 NS_LOG_FUNCTION (this << size << initialChecksum);
1144 /* see RFC 1071 to understand this code. */
1145 uint32_t sum = initialChecksum;
1146
1147 for (int j = 0; j < size/2; j++)
1148 sum += ReadU16 ();
1149
1150 if (size & 1)
1151 sum += ReadU8 ();
1152
1153 while (sum >> 16)
1154 sum = (sum & 0xffff) + (sum >> 16);
1155 return ~sum;
1156}
1157
1158uint32_t
1160{
1161 NS_LOG_FUNCTION (this);
1162 return m_dataEnd - m_dataStart;
1163}
1164
1167{
1168 NS_LOG_FUNCTION (this);
1169 return m_dataEnd - m_current;
1170}
1171
1172
1173std::string
1175{
1176 NS_LOG_FUNCTION (this);
1177 std::string str = "You have attempted to read beyond the bounds of the "
1178 "available buffer space. This usually indicates that a "
1179 "Header::Deserialize or Trailer::Deserialize method "
1180 "is trying to read data which was not written by "
1181 "a Header::Serialize or Trailer::Serialize method. "
1182 "In short: check the code of your Serialize and Deserialize "
1183 "methods.";
1184 return str;
1185}
1186std::string
1188{
1189 NS_LOG_FUNCTION (this);
1190 std::string str;
1191 if (m_current < m_dataStart)
1192 {
1193 str = "You have attempted to write before the start of the available "
1194 "buffer space. This usually indicates that Trailer::GetSerializedSize "
1195 "returned a size which is too small compared to what Trailer::Serialize "
1196 "is actually using.";
1197 }
1198 else if (m_current >= m_dataEnd)
1199 {
1200 str = "You have attempted to write after the end of the available "
1201 "buffer space. This usually indicates that Header::GetSerializedSize "
1202 "returned a size which is too small compared to what Header::Serialize "
1203 "is actually using.";
1204 }
1205 else
1206 {
1207 NS_ASSERT (m_current >= m_zeroStart && m_current < m_zeroEnd);
1208 str = "You have attempted to write inside the payload area of the "
1209 "buffer. This usually indicates that your Serialize method uses more "
1210 "buffer space than what your GetSerialized method returned.";
1211 }
1212 return str;
1213}
1214
1215
1216} // namespace ns3
1217
1218
#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:73
#define DESTROYED
Definition: buffer.cc:76
#define IS_INITIALIZED(x)
Definition: buffer.cc:75
#define IS_DESTROYED(x)
Definition: buffer.cc:74
iterator in a Buffer instance
Definition: buffer.h:99
void WriteU64(uint64_t data)
Definition: buffer.cc:891
void Write(uint8_t const *buffer, uint32_t size)
Definition: buffer.cc:954
void WriteU32(uint32_t data)
Definition: buffer.cc:879
bool IsEnd(void) const
Definition: buffer.cc:804
bool IsStart(void) const
Definition: buffer.cc:810
void WriteHtonU64(uint64_t data)
Definition: buffer.cc:941
void WriteHtolsbU16(uint16_t data)
Definition: buffer.cc:911
uint64_t ReadNtohU64(void)
Definition: buffer.cc:1044
uint32_t ReadLsbtohU32(void)
Definition: buffer.cc:1077
uint16_t CalculateIpChecksum(uint16_t size)
Calculate the checksum.
Definition: buffer.cc:1134
void WriteU8(uint8_t data)
Definition: buffer.h:869
uint8_t * m_data
a pointer to the underlying byte buffer.
Definition: buffer.h:484
uint32_t GetRemainingSize(void) const
Definition: buffer.cc:1166
void WriteHtolsbU32(uint32_t data)
Definition: buffer.cc:918
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:464
bool Check(uint32_t i) const
Checks that the buffer position is not in the "virtual zero area".
Definition: buffer.cc:826
uint32_t SlowReadNtohU32(void)
Definition: buffer.cc:1030
void WriteU16(uint16_t data)
Definition: buffer.cc:871
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:479
void Read(uint8_t *buffer, uint32_t size)
Definition: buffer.cc:1124
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:927
uint16_t ReadLsbtohU16(void)
Definition: buffer.cc:1066
void Prev(void)
go backward by one byte
Definition: buffer.h:851
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:459
std::string GetWriteErrorMessage(void) const
Returns an appropriate message indicating a write error.
Definition: buffer.cc:1187
uint64_t ReadLsbtohU64(void)
Definition: buffer.cc:1094
uint16_t SlowReadNtohU16(void)
Definition: buffer.cc:1020
uint64_t ReadU64(void)
Definition: buffer.cc:990
bool CheckNoZero(uint32_t start, uint32_t end) const
Checks that the [start, end) is not in the "virtual zero area".
Definition: buffer.cc:817
uint32_t GetDistanceFrom(Iterator const &o) const
Definition: buffer.cc:788
std::string GetReadErrorMessage(void) const
Returns an appropriate message indicating a read error.
Definition: buffer.cc:1174
uint32_t GetSize(void) const
Definition: buffer.cc:1159
uint32_t ReadU32(void)
Definition: buffer.cc:973
automatically resized byte buffer
Definition: buffer.h:93
uint32_t GetInternalSize(void) const
Get the buffer real size.
Definition: buffer.cc:296
uint32_t m_end
offset to the end of the data referenced by this Buffer instance from the start of m_data->m_data
Definition: buffer.h:791
bool CheckInternalState(void) const
Checks the internal buffer structures consistency.
Definition: buffer.cc:210
Buffer CreateFragment(uint32_t start, uint32_t length) const
Definition: buffer.cc:524
static FreeList * g_freeList
Buffer data container.
Definition: buffer.h:802
static struct Buffer::Data * Create(uint32_t size)
Create a buffer data storage.
Definition: buffer.cc:119
static uint32_t g_maxSize
Max observed data size.
Definition: buffer.h:801
uint32_t m_zeroAreaEnd
offset to the end of the virtual zero area from the start of m_data->m_data
Definition: buffer.h:781
std::vector< struct Buffer::Data * > FreeList
Container for buffer data.
Definition: buffer.h:795
static void Deallocate(struct Buffer::Data *data)
Deallocate the buffer memory.
Definition: buffer.cc:180
uint32_t m_maxZeroAreaStart
keep track of the maximum value of m_zeroAreaStart across the lifetime of a Buffer instance.
Definition: buffer.h:764
uint32_t GetSize(void) const
Definition: buffer.h:1063
static uint32_t g_recommendedStart
location in a newly-allocated buffer where you should start writing data.
Definition: buffer.h:770
uint32_t GetInternalEnd(void) const
Get the buffer end position.
Definition: buffer.cc:302
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:720
Buffer CreateFullCopy(void) const
Create a full copy of the buffer, including all the internal structures.
Definition: buffer.cc:536
static struct Buffer::Data * Allocate(uint32_t reqSize)
Allocate a buffer data storage.
Definition: buffer.cc:163
Buffer & operator=(Buffer const &o)
Assignment operator.
Definition: buffer.cc:259
void RemoveAtEnd(uint32_t end)
Definition: buffer.cc:488
void AddAtStart(uint32_t start)
Definition: buffer.cc:309
void AddAtEnd(uint32_t end)
Definition: buffer.cc:354
uint32_t GetSerializedSize(void) const
Return the number of bytes required for serialization.
Definition: buffer.cc:561
void TransformIntoRealBuffer(void) const
Transform a "Virtual byte buffer" into a "Real byte buffer".
Definition: buffer.cc:699
static void Recycle(struct Buffer::Data *data)
Recycle the buffer memory.
Definition: buffer.cc:98
struct Data * m_data
the buffer data storage
Definition: buffer.h:752
Buffer::Iterator End(void) const
Definition: buffer.h:1075
uint8_t const * PeekData(void) const
Definition: buffer.cc:710
void Initialize(uint32_t zeroSize)
Initializes the buffer with a number of zeroes.
Definition: buffer.cc:244
Buffer::Iterator Begin(void) const
Definition: buffer.h:1069
uint32_t Deserialize(const uint8_t *buffer, uint32_t size)
Definition: buffer.cc:653
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:443
uint32_t m_zeroAreaStart
offset to the start of the virtual zero area from the start of m_data->m_data
Definition: buffer.h:776
uint32_t Serialize(uint8_t *buffer, uint32_t maxSize) const
Definition: buffer.cc:581
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:786
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#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:88
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
static struct anonymous_namespace{buffer.cc}::Zeroes g_zeroes
Zero-filled buffer.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
def start()
Definition: core.py:1853
uint8_t data[writeSize]
char buffer[1000]
buffer containing zero values
Definition: buffer.cc:42
const uint32_t size
buffer size
Definition: buffer.cc:43
This data structure is variable-sized through its last member whose size is determined at allocation ...
Definition: buffer.h:661
uint8_t m_data[1]
The real data buffer holds at least one byte.
Definition: buffer.h:685
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:680
uint32_t m_count
The reference count of an instance of this data structure.
Definition: buffer.h:666
uint32_t m_size
the size of the m_data field below.
Definition: buffer.h:670
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:675
Local static destructor structure.
Definition: buffer.h:798