Kea 2.5.4
buffer.h
Go to the documentation of this file.
1// Copyright (C) 2009-2022 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#ifndef BUFFER_H
8#define BUFFER_H 1
9
10#include <stdlib.h>
11#include <cstring>
12#include <vector>
13
14#include <stdint.h>
15
17
18#include <boost/shared_ptr.hpp>
19
20namespace isc {
21namespace util {
22
28public:
29 InvalidBufferPosition(const char* file, size_t line, const char* what) :
30 isc::Exception(file, line, what) {}
31};
32
82public:
85
86
92 InputBuffer(const void* data, size_t len) :
93 position_(0), data_(static_cast<const uint8_t*>(data)), len_(len) {}
95
98
99
100 size_t getLength() const { return (len_); }
102 size_t getPosition() const { return (position_); }
104
108
109
115 void setPosition(size_t position) {
116 if (position > len_) {
117 throwError("position is too large");
118 }
119 position_ = position;
120 }
122
125
126
130 uint8_t readUint8() {
131 if (position_ + sizeof(uint8_t) > len_) {
132 throwError("read beyond end of buffer");
133 }
134
135 return (data_[position_++]);
136 }
142 uint16_t readUint16() {
143 uint16_t data;
144 const uint8_t* cp;
145
146 if (position_ + sizeof(data) > len_) {
147 throwError("read beyond end of buffer");
148 }
149
150 cp = &data_[position_];
151 data = ((unsigned int)(cp[0])) << 8;
152 data |= ((unsigned int)(cp[1]));
153 position_ += sizeof(data);
154
155 return (data);
156 }
162 uint32_t readUint32() {
163 uint32_t data;
164 const uint8_t* cp;
165
166 if (position_ + sizeof(data) > len_) {
167 throwError("read beyond end of buffer");
168 }
169
170 cp = &data_[position_];
171 data = ((unsigned int)(cp[0])) << 24;
172 data |= ((unsigned int)(cp[1])) << 16;
173 data |= ((unsigned int)(cp[2])) << 8;
174 data |= ((unsigned int)(cp[3]));
175 position_ += sizeof(data);
176
177 return (data);
178 }
186 void readData(void* data, size_t len) {
187 if (position_ + len > len_) {
188 throwError("read beyond end of buffer");
189 }
190
191 static_cast<void>(std::memmove(data, &data_[position_], len));
192 position_ += len;
193 }
195
204 void readVector(std::vector<uint8_t>& data, size_t len) {
205 if (position_ + len > len_) {
206 throwError("read beyond end of buffer");
207 }
208
209 data.resize(len);
210 readData(&data[0], len);
211 }
212
213private:
219 static void throwError(const char* msg) {
221 }
222
223 size_t position_;
224
225 // XXX: The following must be private, but for a short term workaround with
226 // Boost.Python binding, we changed it to protected. We should soon
227 // revisit it.
228protected:
229 const uint8_t* data_;
230 size_t len_;
231};
232
295public:
299
300
303 OutputBuffer(size_t len) :
304 buffer_(NULL),
305 size_(0),
306 allocated_(len)
307 {
308 // We use malloc and free instead of C++ new[] and delete[].
309 // This way we can use realloc, which may in fact do it without a copy.
310 if (allocated_ != 0) {
311 buffer_ = static_cast<uint8_t*>(malloc(allocated_));
312 if (buffer_ == NULL) {
313 throw std::bad_alloc();
314 }
315 }
316 }
317
326 buffer_(NULL),
327 size_(other.size_),
328 allocated_(other.allocated_)
329 {
330 if (allocated_ != 0) {
331 buffer_ = static_cast<uint8_t*>(malloc(allocated_));
332 if (buffer_ == NULL) {
333 throw std::bad_alloc();
334 }
335 static_cast<void>(std::memmove(buffer_, other.buffer_, other.size_));
336 }
337 }
338
341 free(buffer_);
342 }
344
353 if (this != &other) {
354 // Not self-assignment.
355 if (other.allocated_ != 0) {
356
357 // There is something in the source object, so allocate memory
358 // and copy it. The pointer to the allocated memory is placed
359 // in a temporary variable so that if the allocation fails and
360 // an exception is thrown, the destination object ("this") is
361 // unchanged.
362 uint8_t* newbuff = static_cast<uint8_t*>(malloc(other.allocated_));
363 if (newbuff == NULL) {
364 throw std::bad_alloc();
365 }
366
367 // Memory allocated, update the source object and copy data
368 // across.
369 free(buffer_);
370 buffer_ = newbuff;
371 static_cast<void>(std::memmove(buffer_, other.buffer_, other.size_));
372
373 } else {
374
375 // Nothing allocated in the source object, so zero the buffer
376 // in the destination.
377 free(buffer_);
378 buffer_ = NULL;
379 }
380
381 // Update the other member variables.
382 size_ = other.size_;
383 allocated_ = other.allocated_;
384 }
385 return (*this);
386 }
387
391
392
393 size_t getCapacity() const { return (allocated_); }
401 const void* getData() const { return (buffer_); }
403 size_t getLength() const { return (size_); }
410 uint8_t operator[](size_t pos) const {
411 if (pos >= size_) {
413 "[]: pos (" << pos << ") >= size (" << size_ << ")");
414 }
415 return (buffer_[pos]);
416 }
418
422
423
429 void skip(size_t len) {
430 ensureAllocated(size_ + len);
431 size_ += len;
432 }
433
441 void trim(size_t len) {
442 if (len > size_) {
443 isc_throw(OutOfRange, "trimming too large from output buffer");
444 }
445 size_ -= len;
446 }
451 void clear() { size_ = 0; }
452
456 void wipe() {
457 if (buffer_ != NULL) {
458 static_cast<void>(std::memset(buffer_, 0, allocated_));
459 }
460 size_ = 0;
461 }
462
466 void writeUint8(uint8_t data) {
467 ensureAllocated(size_ + 1);
468 buffer_[size_ ++] = data;
469 }
470
479 void writeUint8At(uint8_t data, size_t pos) {
480 if (pos + sizeof(data) > size_) {
481 isc_throw(InvalidBufferPosition, "write at invalid position");
482 }
483 buffer_[pos] = data;
484 }
485
490 void writeUint16(uint16_t data) {
491 ensureAllocated(size_ + sizeof(data));
492 buffer_[size_ ++] = static_cast<uint8_t>((data & 0xff00U) >> 8);
493 buffer_[size_ ++] = static_cast<uint8_t>(data & 0x00ffU);
494 }
495
507 void writeUint16At(uint16_t data, size_t pos) {
508 if (pos + sizeof(data) > size_) {
509 isc_throw(InvalidBufferPosition, "write at invalid position");
510 }
511
512 buffer_[pos] = static_cast<uint8_t>((data & 0xff00U) >> 8);
513 buffer_[pos + 1] = static_cast<uint8_t>(data & 0x00ffU);
514 }
515
520 void writeUint32(uint32_t data) {
521 ensureAllocated(size_ + sizeof(data));
522 buffer_[size_ ++] = static_cast<uint8_t>((data & 0xff000000) >> 24);
523 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x00ff0000) >> 16);
524 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x0000ff00) >> 8);
525 buffer_[size_ ++] = static_cast<uint8_t>(data & 0x000000ff);
526 }
527
532 void writeUint64(uint64_t data) {
533 ensureAllocated(size_ + sizeof(data));
534 buffer_[size_ ++] = static_cast<uint8_t>((data & 0xff00000000000000) >> 56);
535 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x00ff000000000000) >> 48);
536 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x0000ff0000000000) >> 40);
537 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x000000ff00000000) >> 32);
538 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x00000000ff000000) >> 24);
539 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x0000000000ff0000) >> 16);
540 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x000000000000ff00) >> 8);
541 buffer_[size_ ++] = static_cast<uint8_t>(data & 0x00000000000000ff);
542 }
543
550 void writeData(const void *data, size_t len) {
551 if (len == 0) {
552 return;
553 }
554
555 ensureAllocated(size_ + len);
556 static_cast<void>(std::memmove(buffer_ + size_, data, len));
557 size_ += len;
558 }
560
561private:
563 uint8_t* buffer_;
565 size_t size_;
567 size_t allocated_;
568
575 void ensureAllocated(size_t needed_size) {
576 if (allocated_ < needed_size) {
577 // Guess some bigger size
578 size_t new_size = (allocated_ == 0) ? 1024 : allocated_;
579 while (new_size < needed_size) {
580 new_size *= 2;
581 }
582 // Allocate bigger space. Note that buffer_ may be NULL,
583 // in which case realloc acts as malloc.
584 uint8_t* new_buffer_(static_cast<uint8_t*>(realloc(buffer_,
585 new_size)));
586 if (new_buffer_ == NULL) {
587 // If it fails, the original block is left intact by it
588 throw std::bad_alloc();
589 }
590 buffer_ = new_buffer_;
591 allocated_ = new_size;
592 }
593 }
594};
595
602typedef boost::shared_ptr<InputBuffer> InputBufferPtr;
603typedef boost::shared_ptr<OutputBuffer> OutputBufferPtr;
604
605} // namespace util
606} // namespace isc
607#endif // BUFFER_H
608
609// Local Variables:
610// mode: c++
611// End:
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
The InputBuffer class is a buffer abstraction for manipulating read-only data.
Definition: buffer.h:81
void readVector(std::vector< uint8_t > &data, size_t len)
Read specified number of bytes as a vector.
Definition: buffer.h:204
InputBuffer(const void *data, size_t len)
Constructor from variable length of data.
Definition: buffer.h:92
uint32_t readUint32()
Read an unsigned 32-bit integer in network byte order from the buffer, convert it to host byte order,...
Definition: buffer.h:162
void setPosition(size_t position)
Set the read position of the buffer to the given value.
Definition: buffer.h:115
const uint8_t * data_
Definition: buffer.h:229
size_t getPosition() const
Return the current read position.
Definition: buffer.h:102
uint8_t readUint8()
Read an unsigned 8-bit integer from the buffer and return it.
Definition: buffer.h:130
size_t getLength() const
Return the length of the data stored in the buffer.
Definition: buffer.h:100
void readData(void *data, size_t len)
Read data of the specified length from the buffer and copy it to the caller supplied buffer.
Definition: buffer.h:186
uint16_t readUint16()
Read an unsigned 16-bit integer in network byte order from the buffer, convert it to host byte order,...
Definition: buffer.h:142
A standard DNS module exception that is thrown if an out-of-range buffer operation is being performed...
Definition: buffer.h:27
InvalidBufferPosition(const char *file, size_t line, const char *what)
Definition: buffer.h:29
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:294
~OutputBuffer()
Destructor.
Definition: buffer.h:340
void writeUint16At(uint16_t data, size_t pos)
Write an unsigned 16-bit integer in host byte order at the specified position of the buffer in networ...
Definition: buffer.h:507
OutputBuffer & operator=(const OutputBuffer &other)
Assignment operator.
Definition: buffer.h:352
void wipe()
Wipe buffer content.
Definition: buffer.h:456
void writeUint8At(uint8_t data, size_t pos)
Write an unsigned 8-bit integer into the buffer.
Definition: buffer.h:479
void writeUint64(uint64_t data)
Write an unsigned 64-bit integer in host byte order into the buffer in network byte order.
Definition: buffer.h:532
OutputBuffer(const OutputBuffer &other)
Copy constructor.
Definition: buffer.h:325
void writeUint8(uint8_t data)
Write an unsigned 8-bit integer into the buffer.
Definition: buffer.h:466
void writeUint16(uint16_t data)
Write an unsigned 16-bit integer in host byte order into the buffer in network byte order.
Definition: buffer.h:490
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition: buffer.h:550
void writeUint32(uint32_t data)
Write an unsigned 32-bit integer in host byte order into the buffer in network byte order.
Definition: buffer.h:520
void trim(size_t len)
Trim the specified length of data from the end of the buffer.
Definition: buffer.h:441
OutputBuffer(size_t len)
Constructor from the initial size of the buffer.
Definition: buffer.h:303
void skip(size_t len)
Insert a specified length of gap at the end of the buffer.
Definition: buffer.h:429
uint8_t operator[](size_t pos) const
Return the value of the buffer at the specified position.
Definition: buffer.h:410
size_t getLength() const
Return the length of data written in the buffer.
Definition: buffer.h:403
void clear()
Clear buffer content.
Definition: buffer.h:451
size_t getCapacity() const
Return the current capacity of the buffer.
Definition: buffer.h:393
const void * getData() const
Return a pointer to the head of the data stored in the buffer.
Definition: buffer.h:401
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< InputBuffer > InputBufferPtr
Pointer-like types pointing to InputBuffer or OutputBuffer.
Definition: buffer.h:602
boost::shared_ptr< OutputBuffer > OutputBufferPtr
Definition: buffer.h:603
Defines the logger used by the top-level component of kea-lfc.