A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
buffer.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005,2006,2007 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8#ifndef BUFFER_H
9#define BUFFER_H
10
11#include "ns3/assert.h"
12
13#include <ostream>
14#include <stdint.h>
15#include <vector>
16
17#define BUFFER_FREE_LIST 1
18
19namespace ns3
20{
21
22/**
23 * @ingroup packet
24 *
25 * @brief automatically resized byte buffer
26 *
27 * This represents a buffer of bytes. Its size is
28 * automatically adjusted to hold any data prepended
29 * or appended by the user. Its implementation is optimized
30 * to ensure that the number of buffer resizes is minimized,
31 * by creating new Buffers of the maximum size ever used.
32 * The correct maximum size is learned at runtime during use by
33 * recording the maximum size of each packet.
34 *
35 * @internal
36 * The implementation of the Buffer class uses a COW (Copy On Write)
37 * technique to ensure that the underlying data buffer which holds
38 * the data bytes is shared among a lot of Buffer instances despite
39 * data being added or removed from them.
40 *
41 * When multiple Buffer instances hold a reference to the same
42 * underlying BufferData object, they must be able to detect when
43 * the operation they want to perform should trigger a copy of the
44 * BufferData. If the BufferData::m_count field is one, it means that
45 * there exist only one instance of Buffer which references the
46 * BufferData instance so, it is safe to modify it. It is also
47 * safe to modify the content of a BufferData if the modification
48 * falls outside of the "dirty area" defined by the BufferData.
49 * In every other case, the BufferData must be copied before
50 * being modified.
51 *
52 * To understand the way the Buffer::Add and Buffer::Remove methods
53 * work, you first need to understand the "virtual offsets" used to
54 * keep track of the content of buffers. Each Buffer instance
55 * contains real data bytes in its BufferData instance but it also
56 * contains "virtual zero data" which typically is used to represent
57 * application-level payload. No memory is allocated to store the
58 * zero bytes of application-level payload unless the user fragments
59 * a Buffer: this application-level payload is kept track of with
60 * a pair of integers which describe where in the buffer content
61 * the "virtual zero area" starts and ends.
62 *
63 * @verbatim
64 * ***: unused bytes
65 * xxx: bytes "added" at the front of the zero area
66 * ...: bytes "added" at the back of the zero area
67 * 000: virtual zero bytes
68 *
69 * Real byte buffer: |********xxxxxxxxxxxx.........*****|
70 * |--------^ m_start
71 * |-------------------^ m_zeroAreaStart
72 * |-----------------------------^ m_end - (m_zeroAreaEnd - m_zeroAreaStart)
73 * Virtual byte buffer: |xxxxxxxxxxxx0000000000000.........|
74 * |--------^ m_start
75 * |--------------------^ m_zeroAreaStart
76 * |---------------------------------^ m_zeroAreaEnd
77 * |------------------------------------------^ m_end
78 * @endverbatim
79 *
80 * A simple state invariant is that m_start <= m_zeroStart <= m_zeroEnd <= m_end
81 */
82class Buffer
83{
84 public:
85 /**
86 * @brief iterator in a Buffer instance
87 */
89 {
90 public:
91 inline Iterator();
92 /**
93 * go forward by one byte
94 */
95 inline void Next();
96 /**
97 * go backward by one byte
98 */
99 inline void Prev();
100 /**
101 * @param delta number of bytes to go forward
102 */
103 inline void Next(uint32_t delta);
104 /**
105 * @param delta number of bytes to go backward
106 */
107 inline void Prev(uint32_t delta);
108 /**
109 * @param o the second iterator
110 * @return number of bytes included between the two iterators
111 *
112 * This method works only if the two iterators point
113 * to the same underlying buffer. Debug builds ensure
114 * this with an assert.
115 *
116 * @hidecaller
117 */
118 uint32_t GetDistanceFrom(const Iterator& o) const;
119
120 /**
121 * @return true if this iterator points to the end of the byte array.
122 * false otherwise.
123 */
124 bool IsEnd() const;
125 /**
126 * @return true if this iterator points to the start of the byte array.
127 * false otherwise.
128 */
129 bool IsStart() const;
130
131 /**
132 * @param data data to write in buffer
133 *
134 * Write the data in buffer and advance the iterator position
135 * by one byte.
136 *
137 * @hidecaller
138 */
139 inline void WriteU8(uint8_t data);
140 /**
141 * @param data data to write in buffer
142 * @param len number of times data must be written in buffer
143 *
144 * Write the data in buffer len times and advance the iterator position
145 * by len byte.
146 *
147 * @hidecaller
148 */
149 inline void WriteU8(uint8_t data, uint32_t len);
150 /**
151 * @param data data to write in buffer
152 *
153 * Write the data in buffer and advance the iterator position
154 * by two bytes. The format of the data written in the byte
155 * buffer is non-portable. We only ensure that readU16 will
156 * return exactly what we wrote with writeU16 if the program
157 * is run on the same machine.
158 */
159 void WriteU16(uint16_t data);
160 /**
161 * @param data data to write in buffer
162 *
163 * Write the data in buffer and advance the iterator position
164 * by four bytes. The format of the data written in the byte
165 * buffer is non-portable. We only ensure that readU32 will
166 * return exactly what we wrote with writeU32 if the program
167 * is run on the same machine.
168 */
169 void WriteU32(uint32_t data);
170 /**
171 * @param data data to write in buffer
172 *
173 * Write the data in buffer and advance the iterator position
174 * by eight bytes. The format of the data written in the byte
175 * buffer is non-portable. We only ensure that readU64 will
176 * return exactly what we wrote with writeU64 if the program
177 * is run on the same machine.
178 */
179 void WriteU64(uint64_t data);
180 /**
181 * @param data data to write in buffer
182 *
183 * Write the data in buffer and advance the iterator position
184 * by two bytes. The data is written in least significant byte order and the
185 * input data is expected to be in host order.
186 */
187 void WriteHtolsbU16(uint16_t data);
188 /**
189 * @param data data to write in buffer
190 *
191 * Write the data in buffer and advance the iterator position
192 * by four bytes. The data is written in least significant byte order and the
193 * input data is expected to be in host order.
194 */
196 /**
197 * @param data data to write in buffer
198 *
199 * Write the data in buffer and advance the iterator position
200 * by eight bytes. The data is written in least significant byte order and the
201 * input data is expected to be in host order.
202 */
203 void WriteHtolsbU64(uint64_t data);
204 /**
205 * @param data data to write in buffer
206 *
207 * Write the data in buffer and advance the iterator position
208 * by two bytes. The data is written in network order and the
209 * input data is expected to be in host order.
210 *
211 * @hidecaller
212 */
213 inline void WriteHtonU16(uint16_t data);
214 /**
215 * @param data data to write in buffer
216 *
217 * Write the data in buffer and advance the iterator position
218 * by four bytes. The data is written in network order and the
219 * input data is expected to be in host order.
220 */
221 inline void WriteHtonU32(uint32_t data);
222 /**
223 * @param data data to write in buffer
224 *
225 * Write the data in buffer and advance the iterator position
226 * by eight bytes. The data is written in network order and the
227 * input data is expected to be in host order.
228 */
229 void WriteHtonU64(uint64_t data);
230 /**
231 * @param buffer a byte buffer to copy in the internal buffer.
232 * @param size number of bytes to copy.
233 *
234 * Write the data in buffer and advance the iterator position
235 * by size bytes.
236 */
237 void Write(const uint8_t* buffer, uint32_t size);
238 /**
239 * @param start the start of the data to copy
240 * @param end the end of the data to copy
241 *
242 * Write the data delimited by start and end in internal buffer
243 * and advance the iterator position by the number of bytes
244 * copied.
245 * The input iterators _must_ not point to the same Buffer as
246 * we do to avoid overlapping copies. This is enforced
247 * in debug builds by asserts.
248 */
249 void Write(Iterator start, Iterator end);
250
251 /**
252 * @return the byte read in the buffer.
253 *
254 * Read data, but do not advance the Iterator read.
255 */
256 inline uint8_t PeekU8();
257
258 /**
259 * @return the byte read in the buffer.
260 *
261 * Read data and advance the Iterator by the number of bytes
262 * read.
263 *
264 * @hidecaller
265 */
266 inline uint8_t ReadU8();
267 /**
268 * @return the two bytes read in the buffer.
269 *
270 * Read data and advance the Iterator by the number of bytes
271 * read.
272 * The data is read in the format written by writeU16.
273 */
274 inline uint16_t ReadU16();
275 /**
276 * @return the four bytes read in the buffer.
277 *
278 * Read data and advance the Iterator by the number of bytes
279 * read.
280 * The data is read in the format written by writeU32.
281 */
283 /**
284 * @return the eight bytes read in the buffer.
285 *
286 * Read data and advance the Iterator by the number of bytes
287 * read.
288 * The data is read in the format written by writeU64.
289 */
290 uint64_t ReadU64();
291 /**
292 * @return the two bytes read in the buffer.
293 *
294 * Read data and advance the Iterator by the number of bytes
295 * read.
296 * The data is read in network format and returned in host format.
297 *
298 * @hidecaller
299 */
300 inline uint16_t ReadNtohU16();
301 /**
302 * @return the four bytes read in the buffer.
303 *
304 * Read data and advance the Iterator by the number of bytes
305 * read.
306 * The data is read in network format and returned in host format.
307 */
308 inline uint32_t ReadNtohU32();
309 /**
310 * @return the eight bytes read in the buffer.
311 *
312 * Read data and advance the Iterator by the number of bytes
313 * read.
314 * The data is read in network format and returned in host format.
315 */
316 uint64_t ReadNtohU64();
317 /**
318 * @return the two bytes read in the buffer.
319 *
320 * Read data and advance the Iterator by the number of bytes
321 * read.
322 * The data is read in least significant byte format and returned in host format.
323 */
324 uint16_t ReadLsbtohU16();
325 /**
326 * @return the four bytes read in the buffer.
327 *
328 * Read data and advance the Iterator by the number of bytes
329 * read.
330 * The data is read in least significant byte format and returned in host format.
331 */
333 /**
334 * @return the eight bytes read in the buffer.
335 *
336 * Read data and advance the Iterator by the number of bytes
337 * read.
338 * The data is read in least significant byte format and returned in host format.
339 */
340 uint64_t ReadLsbtohU64();
341 /**
342 * @param buffer buffer to copy data into
343 * @param size number of bytes to copy
344 *
345 * Copy size bytes of data from the internal buffer to the
346 * input buffer and advance the Iterator by the number of
347 * bytes read.
348 */
349 void Read(uint8_t* buffer, uint32_t size);
350
351 /**
352 * @param start start iterator of the buffer to copy data into
353 * @param size number of bytes to copy
354 *
355 * Copy size bytes of data from the internal buffer to the input buffer via
356 * the provided iterator and advance the Iterator by the number of bytes
357 * read.
358 */
359 inline void Read(Iterator start, uint32_t size);
360
361 /**
362 * @brief Calculate the checksum.
363 * @param size size of the buffer.
364 * @return checksum
365 */
366 uint16_t CalculateIpChecksum(uint16_t size);
367
368 /**
369 * @brief Calculate the checksum.
370 * @param size size of the buffer.
371 * @param initialChecksum initial value
372 * @return checksum
373 */
374 uint16_t CalculateIpChecksum(uint16_t size, uint32_t initialChecksum);
375
376 /**
377 * @returns the size of the underlying buffer we are iterating
378 */
379 uint32_t GetSize() const;
380
381 /**
382 * @returns the size left to read of the underlying buffer we are iterating
383 */
385
386 private:
387 /// Friend class
388 friend class Buffer;
389 /**
390 * Constructor - initializes the iterator to point to the buffer start
391 *
392 * @param buffer the buffer this iterator refers to
393 */
394 inline Iterator(const Buffer* buffer);
395 /**
396 * Constructor - initializes the iterator to point to the buffer end
397 *
398 * @param buffer the buffer this iterator refers to
399 * @param dummy not used param
400 */
401 inline Iterator(const Buffer* buffer, bool dummy);
402 /**
403 * Initializes the iterator values
404 *
405 * @param buffer the buffer this iterator refers to
406 */
407 inline void Construct(const Buffer* buffer);
408 /**
409 * Checks that the [start, end) is not in the "virtual zero area".
410 *
411 * @param start start buffer position
412 * @param end end buffer position
413 * @returns true if [start, end) is not in the "virtual zero area".
414 */
415 bool CheckNoZero(uint32_t start, uint32_t end) const;
416 /**
417 * Checks that the buffer position is not in the "virtual zero area".
418 *
419 * @param i buffer position
420 * @returns true if not in the "virtual zero area".
421 */
422 bool Check(uint32_t i) const;
423 /**
424 * @return the two bytes read in the buffer.
425 *
426 * Read data and advance the Iterator by the number of bytes
427 * read.
428 * The data is read in network format and returned in host format.
429 *
430 * @warning this is the slow version, please use ReadNtohU16 ()
431 */
432 uint16_t SlowReadNtohU16();
433 /**
434 * @return the four bytes read in the buffer.
435 *
436 * Read data and advance the Iterator by the number of bytes
437 * read.
438 * The data is read in network format and returned in host format.
439 *
440 * @warning this is the slow version, please use ReadNtohU32 ()
441 */
443 /**
444 * @brief Returns an appropriate message indicating a read error
445 * @returns the error message
446 */
447 std::string GetReadErrorMessage() const;
448 /**
449 * @brief Returns an appropriate message indicating a write error
450 *
451 * The message depends on the actual Buffer::Iterator status.
452 *
453 * @returns the error message
454 */
455 std::string GetWriteErrorMessage() const;
456
457 /**
458 * offset in virtual bytes from the start of the data buffer to the
459 * start of the "virtual zero area".
460 */
462 /**
463 * offset in virtual bytes from the start of the data buffer to the
464 * end of the "virtual zero area".
465 */
467 /**
468 * offset in virtual bytes from the start of the data buffer to the
469 * start of the data which can be read by this iterator
470 */
472 /**
473 * offset in virtual bytes from the start of the data buffer to the
474 * end of the data which can be read by this iterator
475 */
477 /**
478 * offset in virtual bytes from the start of the data buffer to the
479 * current position represented by this iterator.
480 */
482 /**
483 * a pointer to the underlying byte buffer. All offsets are relative
484 * to this pointer.
485 */
486 uint8_t* m_data;
487 };
488
489 /**
490 * @return the number of bytes stored in this buffer.
491 */
492 inline uint32_t GetSize() const;
493
494 /**
495 * @return a pointer to the start of the internal
496 * byte buffer.
497 *
498 * The returned pointer points to an area of
499 * memory which is ns3::Buffer::GetSize () bytes big.
500 * Please, try to never ever use this method. It is really
501 * evil and is present only for a few specific uses.
502 */
503 const uint8_t* PeekData() const;
504
505 /**
506 * @param start size to reserve
507 *
508 * Add bytes at the start of the Buffer. The
509 * content of these bytes is undefined but debugging
510 * builds initialize them to 0x33.
511 * Any call to this method invalidates any Iterator
512 * pointing to this Buffer.
513 */
514 void AddAtStart(uint32_t start);
515 /**
516 * @param end size to reserve
517 *
518 * Add bytes at the end of the Buffer. The
519 * content of these bytes is undefined but debugging
520 * builds initialize them to 0x33.
521 * Any call to this method invalidates any Iterator
522 * pointing to this Buffer.
523 */
524 void AddAtEnd(uint32_t end);
525
526 /**
527 * @param o the buffer to append to the end of this buffer.
528 *
529 * Add bytes at the end of the Buffer.
530 * Any call to this method invalidates any Iterator
531 * pointing to this Buffer.
532 */
533 void AddAtEnd(const Buffer& o);
534 /**
535 * @param start size to remove
536 *
537 * Remove bytes at the start of the Buffer.
538 * Any call to this method invalidates any Iterator
539 * pointing to this Buffer.
540 */
541 void RemoveAtStart(uint32_t start);
542 /**
543 * @param end size to remove
544 *
545 * Remove bytes at the end of the Buffer.
546 * Any call to this method invalidates any Iterator
547 * pointing to this Buffer.
548 */
549 void RemoveAtEnd(uint32_t end);
550
551 /**
552 * @param start offset from start of packet
553 * @param length
554 *
555 * @return a fragment of size length starting at offset
556 * start.
557 */
558 Buffer CreateFragment(uint32_t start, uint32_t length) const;
559
560 /**
561 * @return an Iterator which points to the
562 * start of this Buffer.
563 */
564 inline Buffer::Iterator Begin() const;
565 /**
566 * @return an Iterator which points to the
567 * end of this Buffer.
568 */
569 inline Buffer::Iterator End() const;
570
571 /**
572 * @brief Return the number of bytes required for serialization.
573 * @return the number of bytes.
574 */
576
577 /**
578 * @return zero if buffer not large enough
579 * @param buffer points to serialization buffer
580 * @param maxSize max number of bytes to write
581 *
582 * This buffer's contents are serialized into the raw
583 * character buffer parameter. Note: The zero length
584 * data is not copied entirely. Only the length of
585 * zero byte data is serialized.
586 */
587 uint32_t Serialize(uint8_t* buffer, uint32_t maxSize) const;
588
589 /**
590 * @return zero if a complete buffer is not deserialized
591 * @param buffer points to buffer for deserialization
592 * @param size number of bytes to deserialize
593 *
594 * The raw character buffer is deserialized and all the
595 * data is placed into this buffer.
596 */
597 uint32_t Deserialize(const uint8_t* buffer, uint32_t size);
598
599 /**
600 * Copy the specified amount of data from the buffer to the given output stream.
601 *
602 * @param os the output stream
603 * @param size the maximum amount of bytes to copy. If zero, nothing is copied.
604 */
605 void CopyData(std::ostream* os, uint32_t size) const;
606
607 /**
608 * Copy the specified amount of data from the buffer to the given buffer.
609 *
610 * @param buffer the output buffer
611 * @param size the maximum amount of bytes to copy. If zero, nothing is copied.
612 * @returns the amount of bytes copied
613 */
614 uint32_t CopyData(uint8_t* buffer, uint32_t size) const;
615
616 /**
617 * @brief Copy constructor
618 * @param o the buffer to copy
619 */
620 inline Buffer(const Buffer& o);
621 /**
622 * @brief Assignment operator
623 * @param o the buffer to copy
624 * @return a reference to the buffer
625 */
626 Buffer& operator=(const Buffer& o);
627 Buffer();
628 /**
629 * @brief Constructor
630 *
631 * The buffer will be initialized with zeroes up to its size.
632 *
633 * @param dataSize the buffer size
634 */
635 Buffer(uint32_t dataSize);
636 /**
637 * @brief Constructor
638 *
639 * If initialize is set to true, the buffer will be initialized
640 * with zeroes up to its size.
641 *
642 * @param dataSize the buffer size.
643 * @param initialize initialize the buffer with zeroes.
644 */
645 Buffer(uint32_t dataSize, bool initialize);
646 ~Buffer();
647
648 private:
649 /**
650 * This data structure is variable-sized through its last member whose size
651 * is determined at allocation time and stored in the m_size field.
652 *
653 * The so-called "dirty area" describes the area in the buffer which
654 * has been reserved and used by a user. Multiple Buffer instances
655 * may reference the same Buffer::Data object instance and may
656 * reference different parts of the underlying byte buffer. The
657 * "dirty area" is union of all the areas referenced by the Buffer
658 * instances which reference the same BufferData instance.
659 * New user data can be safely written only outside of the "dirty
660 * area" if the reference count is higher than 1 (that is, if
661 * more than one Buffer instance references the same BufferData).
662 */
663 struct Data
664 {
665 /**
666 * The reference count of an instance of this data structure.
667 * Each buffer which references an instance holds a count.
668 */
670 /**
671 * the size of the m_data field below.
672 */
674 /**
675 * offset from the start of the m_data field below to the
676 * start of the area in which user bytes were written.
677 */
679 /**
680 * offset from the start of the m_data field below to the
681 * end of the area in which user bytes were written.
682 */
684 /**
685 * The real data buffer holds _at least_ one byte.
686 * Its real size is stored in the m_size field.
687 */
688 uint8_t m_data[1];
689 };
690
691 /**
692 * @brief Create a full copy of the buffer, including
693 * all the internal structures.
694 *
695 * @returns a copy of the buffer
696 */
697 Buffer CreateFullCopy() const;
698
699 /**
700 * @brief Transform a "Virtual byte buffer" into a "Real byte buffer"
701 */
702 void TransformIntoRealBuffer() const;
703 /**
704 * @brief Checks the internal buffer structures consistency
705 *
706 * Used only for debugging purposes.
707 *
708 * @returns true if the buffer status is consistent.
709 */
710 bool CheckInternalState() const;
711
712 /**
713 * @brief Initializes the buffer with a number of zeroes.
714 *
715 * @param zeroSize the zeroes size
716 */
717 void Initialize(uint32_t zeroSize);
718
719 /**
720 * @brief Get the buffer real size.
721 * @warning The real size is the actual memory used by the buffer.
722 * @returns the memory used by the buffer.
723 */
725
726 /**
727 * @brief Get the buffer end position.
728 * @returns the buffer end index.
729 */
730 uint32_t GetInternalEnd() const;
731
732 /**
733 * @brief Recycle the buffer memory
734 * @param data the buffer data storage
735 */
736 static void Recycle(Buffer::Data* data);
737 /**
738 * @brief Create a buffer data storage
739 * @param size the storage size to create
740 * @returns a pointer to the created buffer storage
741 */
742 static Buffer::Data* Create(uint32_t size);
743 /**
744 * @brief Allocate a buffer data storage
745 * @param reqSize the storage size to create
746 * @returns a pointer to the allocated buffer storage
747 */
748 static Buffer::Data* Allocate(uint32_t reqSize);
749 /**
750 * @brief Deallocate the buffer memory
751 * @param data the buffer data storage
752 */
753 static void Deallocate(Buffer::Data* data);
754
755 Data* m_data; //!< the buffer data storage
756
757 /**
758 * keep track of the maximum value of m_zeroAreaStart across
759 * the lifetime of a Buffer instance. This variable is used
760 * purely as a source of information for the heuristics which
761 * decide on the position of the zero area in new buffers.
762 * It is read from the Buffer destructor to update the global
763 * heuristic data and these global heuristic data are used from
764 * the Buffer constructor to choose an initial value for
765 * m_zeroAreaStart.
766 */
768 /**
769 * location in a newly-allocated buffer where you should start
770 * writing data. i.e., m_start should be initialized to this
771 * value.
772 */
774
775 /**
776 * offset to the start of the virtual zero area from the start
777 * of m_data->m_data
778 */
780 /**
781 * offset to the end of the virtual zero area from the start
782 * of m_data->m_data
783 */
785 /**
786 * offset to the start of the data referenced by this Buffer
787 * instance from the start of m_data->m_data
788 */
790 /**
791 * offset to the end of the data referenced by this Buffer
792 * instance from the start of m_data->m_data
793 */
795
796#ifdef BUFFER_FREE_LIST
797 /// Container for buffer data
798 typedef std::vector<Buffer::Data*> FreeList;
799
800 /// Local static destructor structure
805
806 static uint32_t g_maxSize; //!< Max observed data size
807 static FreeList* g_freeList; //!< Buffer data container
808 static LocalStaticDestructor g_localStaticDestructor; //!< Local static destructor
809#endif
810};
811
812} // namespace ns3
813
814#include "ns3/assert.h"
815
816#include <cstring>
817
818namespace ns3
819{
820
822 : m_zeroStart(0),
823 m_zeroEnd(0),
824 m_dataStart(0),
825 m_dataEnd(0),
826 m_current(0),
827 m_data(nullptr)
828{
829}
830
832{
833 Construct(buffer);
835}
836
837Buffer::Iterator::Iterator(const Buffer* buffer, bool dummy)
838{
839 Construct(buffer);
841}
842
843void
845{
847 m_zeroEnd = buffer->m_zeroAreaEnd;
848 m_dataStart = buffer->m_start;
849 m_dataEnd = buffer->m_end;
850 m_data = buffer->m_data->m_data;
851}
852
853void
859
860void
866
867void
869{
870 NS_ASSERT(m_current + delta <= m_dataEnd);
871 m_current += delta;
872}
873
874void
876{
877 NS_ASSERT(m_current >= delta);
878 m_current -= delta;
879}
880
881void
883{
885
887 {
889 m_current++;
890 }
891 else
892 {
894 m_current++;
895 }
896}
897
898void
900{
902 if (m_current <= m_zeroStart)
903 {
904 std::memset(&(m_data[m_current]), data, len);
905 m_current += len;
906 }
907 else
908 {
909 uint8_t* buffer = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
910 std::memset(buffer, data, len);
911 m_current += len;
912 }
913}
914
915void
917{
919 uint8_t* buffer;
920 if (m_current + 2 <= m_zeroStart)
921 {
922 buffer = &m_data[m_current];
923 }
924 else
925 {
926 buffer = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
927 }
928 buffer[0] = (data >> 8) & 0xff;
929 buffer[1] = (data >> 0) & 0xff;
930 m_current += 2;
931}
932
933void
935{
937
938 uint8_t* buffer;
939 if (m_current + 4 <= m_zeroStart)
940 {
941 buffer = &m_data[m_current];
942 }
943 else
944 {
945 buffer = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
946 }
947 buffer[0] = (data >> 24) & 0xff;
948 buffer[1] = (data >> 16) & 0xff;
949 buffer[2] = (data >> 8) & 0xff;
950 buffer[3] = (data >> 0) & 0xff;
951 m_current += 4;
952}
953
954uint16_t
956{
957 uint8_t* buffer;
958 if (m_current + 2 <= m_zeroStart)
959 {
960 buffer = &m_data[m_current];
961 }
962 else if (m_current >= m_zeroEnd)
963 {
964 buffer = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
965 }
966 else
967 {
968 return SlowReadNtohU16();
969 }
970 uint16_t retval = 0;
971 retval |= buffer[0];
972 retval <<= 8;
973 retval |= buffer[1];
974 m_current += 2;
975 return retval;
976}
977
980{
981 uint8_t* buffer;
982 if (m_current + 4 <= m_zeroStart)
983 {
984 buffer = &m_data[m_current];
985 }
986 else if (m_current >= m_zeroEnd)
987 {
988 buffer = &m_data[m_current - (m_zeroEnd - m_zeroStart)];
989 }
990 else
991 {
992 return SlowReadNtohU32();
993 }
994 uint32_t retval = 0;
995 retval |= buffer[0];
996 retval <<= 8;
997 retval |= buffer[1];
998 retval <<= 8;
999 retval |= buffer[2];
1000 retval <<= 8;
1001 retval |= buffer[3];
1002 m_current += 4;
1003 return retval;
1004}
1005
1006uint8_t
1008{
1010
1011 if (m_current < m_zeroStart)
1012 {
1013 uint8_t data = m_data[m_current];
1014 return data;
1015 }
1016 else if (m_current < m_zeroEnd)
1017 {
1018 return 0;
1019 }
1020 else
1021 {
1022 uint8_t data = m_data[m_current - (m_zeroEnd - m_zeroStart)];
1023 return data;
1024 }
1025}
1026
1027uint8_t
1029{
1030 uint8_t ret = PeekU8();
1031 m_current++;
1032 return ret;
1033}
1034
1035uint16_t
1037{
1038 uint8_t byte0 = ReadU8();
1039 uint8_t byte1 = ReadU8();
1040 uint16_t data = byte1;
1041 data <<= 8;
1042 data |= byte0;
1043
1044 return data;
1045}
1046
1047void
1049{
1050 Buffer::Iterator end = *this;
1051 end.Next(size);
1052
1053 start.Write(*this, end);
1054}
1055
1067
1070{
1071 return m_end - m_start;
1072}
1073
1076{
1078 return Buffer::Iterator(this);
1079}
1080
1083{
1085 return Buffer::Iterator(this, false);
1086}
1087
1088} // namespace ns3
1089
1090#endif /* BUFFER_H */
iterator in a Buffer instance
Definition buffer.h:89
void WriteU64(uint64_t data)
Definition buffer.cc:870
uint32_t GetRemainingSize() const
Definition buffer.cc:1162
void Construct(const Buffer *buffer)
Initializes the iterator values.
Definition buffer.h:844
uint64_t ReadU64()
Definition buffer.cc:973
void WriteU32(uint32_t data)
Definition buffer.cc:857
uint32_t m_dataEnd
offset in virtual bytes from the start of the data buffer to the end of the data which can be read by...
Definition buffer.h:476
void WriteHtonU64(uint64_t data)
Definition buffer.cc:923
void WriteHtolsbU16(uint16_t data)
Definition buffer.cc:891
uint32_t m_dataStart
offset in virtual bytes from the start of the data buffer to the start of the data which can be read ...
Definition buffer.h:471
uint64_t ReadNtohU64()
Definition buffer.cc:1030
std::string GetReadErrorMessage() const
Returns an appropriate message indicating a read error.
Definition buffer.cc:1169
uint16_t CalculateIpChecksum(uint16_t size)
Calculate the checksum.
Definition buffer.cc:1124
void WriteU8(uint8_t data)
Definition buffer.h:882
uint16_t SlowReadNtohU16()
Definition buffer.cc:1004
uint8_t * m_data
a pointer to the underlying byte buffer.
Definition buffer.h:486
void WriteHtolsbU32(uint32_t data)
Definition buffer.cc:899
void Write(const uint8_t *buffer, uint32_t size)
Definition buffer.cc:937
uint32_t m_zeroEnd
offset in virtual bytes from the start of the data buffer to the end of the "virtual zero area".
Definition buffer.h:466
uint16_t ReadLsbtohU16()
Definition buffer.cc:1053
bool Check(uint32_t i) const
Checks that the buffer position is not in the "virtual zero area".
Definition buffer.cc:807
friend class Buffer
Friend class.
Definition buffer.h:388
void WriteU16(uint16_t data)
Definition buffer.cc:848
uint32_t m_current
offset in virtual bytes from the start of the data buffer to the current position represented by this...
Definition buffer.h:481
uint32_t SlowReadNtohU32()
Definition buffer.cc:1015
void Read(uint8_t *buffer, uint32_t size)
Definition buffer.cc:1114
uint64_t ReadLsbtohU64()
Definition buffer.cc:1083
void WriteHtolsbU64(uint64_t data)
Definition buffer.cc:909
void WriteHtonU16(uint16_t data)
Definition buffer.h:916
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:461
bool CheckNoZero(uint32_t start, uint32_t end) const
Checks that the [start, end) is not in the "virtual zero area".
Definition buffer.cc:799
uint32_t ReadNtohU32()
Definition buffer.h:979
bool IsEnd() const
Definition buffer.cc:785
bool IsStart() const
Definition buffer.cc:792
uint32_t ReadU32()
Definition buffer.cc:955
void WriteHtonU32(uint32_t data)
Definition buffer.h:934
uint16_t ReadNtohU16()
Definition buffer.h:955
uint32_t GetDistanceFrom(const Iterator &o) const
Definition buffer.cc:769
void Prev()
go backward by one byte
Definition buffer.h:861
uint32_t GetSize() const
Definition buffer.cc:1155
uint16_t ReadU16()
Definition buffer.h:1036
std::string GetWriteErrorMessage() const
Returns an appropriate message indicating a write error.
Definition buffer.cc:1183
uint32_t ReadLsbtohU32()
Definition buffer.cc:1065
void Next()
go forward by one byte
Definition buffer.h:854
uint32_t GetSerializedSize() const
Return the number of bytes required for serialization.
Definition buffer.cc:555
std::vector< Buffer::Data * > FreeList
Container for buffer data.
Definition buffer.h:798
uint32_t GetInternalEnd() const
Get the buffer end position.
Definition buffer.cc:296
uint32_t m_end
offset to the end of the data referenced by this Buffer instance from the start of m_data->m_data
Definition buffer.h:794
static Buffer::Data * Allocate(uint32_t reqSize)
Allocate a buffer data storage.
Definition buffer.cc:155
Buffer CreateFragment(uint32_t start, uint32_t length) const
Definition buffer.cc:518
static FreeList * g_freeList
Buffer data container.
Definition buffer.h:807
Data * m_data
the buffer data storage
Definition buffer.h:755
static Buffer::Data * Create(uint32_t size)
Create a buffer data storage.
Definition buffer.cc:109
static uint32_t g_maxSize
Max observed data size.
Definition buffer.h:806
static LocalStaticDestructor g_localStaticDestructor
Local static destructor.
Definition buffer.h:808
uint32_t m_zeroAreaEnd
offset to the end of the virtual zero area from the start of m_data->m_data
Definition buffer.h:784
uint32_t m_maxZeroAreaStart
keep track of the maximum value of m_zeroAreaStart across the lifetime of a Buffer instance.
Definition buffer.h:767
static uint32_t g_recommendedStart
location in a newly-allocated buffer where you should start writing data.
Definition buffer.h:773
static void Deallocate(Buffer::Data *data)
Deallocate the buffer memory.
Definition buffer.cc:173
void CopyData(std::ostream *os, uint32_t size) const
Copy the specified amount of data from the buffer to the given output stream.
Definition buffer.cc:702
void RemoveAtEnd(uint32_t end)
Definition buffer.cc:482
void TransformIntoRealBuffer() const
Transform a "Virtual byte buffer" into a "Real byte buffer".
Definition buffer.cc:682
uint32_t GetSize() const
Definition buffer.h:1069
void AddAtStart(uint32_t start)
Definition buffer.cc:303
uint32_t GetInternalSize() const
Get the buffer real size.
Definition buffer.cc:289
Buffer::Iterator Begin() const
Definition buffer.h:1075
void AddAtEnd(uint32_t end)
Definition buffer.cc:349
Buffer::Iterator End() const
Definition buffer.h:1082
Buffer & operator=(const Buffer &o)
Assignment operator.
Definition buffer.cc:252
Buffer(const Buffer &o)
Copy constructor.
Definition buffer.h:1056
Buffer CreateFullCopy() const
Create a full copy of the buffer, including all the internal structures.
Definition buffer.cc:530
static void Recycle(Buffer::Data *data)
Recycle the buffer memory.
Definition buffer.cc:90
bool CheckInternalState() const
Checks the internal buffer structures consistency.
Definition buffer.cc:203
void Initialize(uint32_t zeroSize)
Initializes the buffer with a number of zeroes.
Definition buffer.cc:237
uint32_t Deserialize(const uint8_t *buffer, uint32_t size)
Definition buffer.cc:637
void RemoveAtStart(uint32_t start)
Definition buffer.cc:436
uint32_t m_zeroAreaStart
offset to the start of the virtual zero area from the start of m_data->m_data
Definition buffer.h:779
uint32_t Serialize(uint8_t *buffer, uint32_t maxSize) const
Definition buffer.cc:571
const uint8_t * PeekData() const
Definition buffer.cc:692
uint32_t m_start
offset to the start of the data referenced by this Buffer instance from the start of m_data->m_data
Definition buffer.h:789
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint8_t data[writeSize]
This data structure is variable-sized through its last member whose size is determined at allocation ...
Definition buffer.h:664
uint8_t m_data[1]
The real data buffer holds at least one byte.
Definition buffer.h:688
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:683
uint32_t m_count
The reference count of an instance of this data structure.
Definition buffer.h:669
uint32_t m_size
the size of the m_data field below.
Definition buffer.h:673
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:678
Local static destructor structure.
Definition buffer.h:802