Kea  1.9.9-git
buffer.h
Go to the documentation of this file.
1 // Copyright (C) 2009-2020 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 
16 #include <exceptions/exceptions.h>
17 
18 #include <boost/shared_ptr.hpp>
19 
20 namespace isc {
21 namespace util {
22 
28 public:
29  InvalidBufferPosition(const char* file, size_t line, const char* what) :
30  isc::Exception(file, line, what) {}
31 };
32 
81 class InputBuffer {
82 public:
85 
86  InputBuffer(const void* data, size_t len) :
93  position_(0), data_(static_cast<const uint8_t*>(data)), len_(len) {}
95 
98 
99  size_t getLength() const { return (len_); }
102  size_t getPosition() const { return (position_); }
104 
108 
109  void setPosition(size_t position) {
116  if (position > len_) {
117  throwError("position is too large");
118  }
119  position_ = position;
120  }
122 
125 
126  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 
213 private:
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.
228 protected:
229  const uint8_t* data_;
230  size_t len_;
231 };
232 
295 public:
299 
300  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 
325  OutputBuffer(const OutputBuffer& other) :
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  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  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  ensureAllocated(size_ + len);
552  static_cast<void>(std::memmove(buffer_ + size_, data, len));
553  size_ += len;
554  }
556 
557 private:
559  uint8_t* buffer_;
561  size_t size_;
563  size_t allocated_;
564 
571  void ensureAllocated(size_t needed_size) {
572  if (allocated_ < needed_size) {
573  // Guess some bigger size
574  size_t new_size = (allocated_ == 0) ? 1024 : allocated_;
575  while (new_size < needed_size) {
576  new_size *= 2;
577  }
578  // Allocate bigger space. Note that buffer_ may be NULL,
579  // in which case realloc acts as malloc.
580  uint8_t* new_buffer_(static_cast<uint8_t*>(realloc(buffer_,
581  new_size)));
582  if (new_buffer_ == NULL) {
583  // If it fails, the original block is left intact by it
584  throw std::bad_alloc();
585  }
586  buffer_ = new_buffer_;
587  allocated_ = new_size;
588  }
589  }
590 };
591 
598 typedef boost::shared_ptr<InputBuffer> InputBufferPtr;
599 typedef boost::shared_ptr<OutputBuffer> OutputBufferPtr;
600 
601 } // namespace util
602 } // namespace isc
603 #endif // BUFFER_H
604 
605 // Local Variables:
606 // mode: c++
607 // End:
size_t getLength() const
Return the length of the data stored in the buffer.
Definition: buffer.h:100
void readVector(std::vector< uint8_t > &data, size_t len)
Read specified number of bytes as a vector.
Definition: buffer.h:204
const void * getData() const
Return a pointer to the head of the data stored in the buffer.
Definition: buffer.h:401
void setPosition(size_t position)
Set the read position of the buffer to the given value.
Definition: buffer.h:115
size_t getCapacity() const
Return the current capacity of the buffer.
Definition: buffer.h:393
void skip(size_t len)
Insert a specified length of gap at the end of the buffer.
Definition: buffer.h:429
InputBuffer(const void *data, size_t len)
Constructor from variable length of data.
Definition: buffer.h:92
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
void trim(size_t len)
Trim the specified length of data from the end of the buffer.
Definition: buffer.h:441
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition: buffer.h:550
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
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
void wipe()
Wipe buffer content.
Definition: buffer.h:456
OutputBuffer(size_t len)
Constructor from the initial size of the buffer.
Definition: buffer.h:303
boost::shared_ptr< InputBuffer > InputBufferPtr
Pointer-like types pointing to InputBuffer or OutputBuffer.
Definition: buffer.h:598
void clear()
Clear buffer content.
Definition: buffer.h:451
A standard DNS module exception that is thrown if an out-of-range buffer operation is being performed...
Definition: buffer.h:27
uint8_t operator[](size_t pos) const
Return the value of the buffer at the specified position.
Definition: buffer.h:410
OutputBuffer(const OutputBuffer &other)
Copy constructor.
Definition: buffer.h:325
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:294
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
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
This is a base class for exceptions thrown from the DNS library module.
Defines the logger used by the top-level component of kea-dhcp-ddns.
size_t getPosition() const
Return the current read position.
Definition: buffer.h:102
const uint8_t * data_
Definition: buffer.h:229
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
~OutputBuffer()
Destructor.
Definition: buffer.h:340
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
void writeUint8(uint8_t data)
Write an unsigned 8-bit integer into the buffer.
Definition: buffer.h:466
InvalidBufferPosition(const char *file, size_t line, const char *what)
Definition: buffer.h:29
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
The InputBuffer class is a buffer abstraction for manipulating read-only data.
Definition: buffer.h:81
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
boost::shared_ptr< OutputBuffer > OutputBufferPtr
Definition: buffer.h:599
uint8_t readUint8()
Read an unsigned 8-bit integer from the buffer and return it.
Definition: buffer.h:130
OutputBuffer & operator=(const OutputBuffer &other)
Assignment operator.
Definition: buffer.h:352
void writeUint8At(uint8_t data, size_t pos)
Write an unsigned 8-bit integer into the buffer.
Definition: buffer.h:479
size_t getLength() const
Return the length of data written in the buffer.
Definition: buffer.h:403