Kea 1.5.0
buffer.h
Go to the documentation of this file.
1// Copyright (C) 2009-2018 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
340 ~ OutputBuffer() {
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 assert (pos < size_);
412 return (buffer_[pos]);
413 }
415
419
420
426 void skip(size_t len) {
427 ensureAllocated(size_ + len);
428 size_ += len;
429 }
430
438 void trim(size_t len) {
439 if (len > size_) {
440 isc_throw(OutOfRange, "trimming too large from output buffer");
441 }
442 size_ -= len;
443 }
448 void clear() { size_ = 0; }
449
453 void wipe() {
454 if (buffer_ != NULL) {
455 static_cast<void>(std::memset(buffer_, 0, allocated_));
456 }
457 size_ = 0;
458 }
459
463 void writeUint8(uint8_t data) {
464 ensureAllocated(size_ + 1);
465 buffer_[size_ ++] = data;
466 }
467
476 void writeUint8At(uint8_t data, size_t pos) {
477 if (pos + sizeof(data) > size_) {
478 isc_throw(InvalidBufferPosition, "write at invalid position");
479 }
480 buffer_[pos] = data;
481 }
482
487 void writeUint16(uint16_t data) {
488 ensureAllocated(size_ + sizeof(data));
489 buffer_[size_ ++] = static_cast<uint8_t>((data & 0xff00U) >> 8);
490 buffer_[size_ ++] = static_cast<uint8_t>(data & 0x00ffU);
491 }
492
504 void writeUint16At(uint16_t data, size_t pos) {
505 if (pos + sizeof(data) > size_) {
506 isc_throw(InvalidBufferPosition, "write at invalid position");
507 }
508
509 buffer_[pos] = static_cast<uint8_t>((data & 0xff00U) >> 8);
510 buffer_[pos + 1] = static_cast<uint8_t>(data & 0x00ffU);
511 }
512
517 void writeUint32(uint32_t data) {
518 ensureAllocated(size_ + sizeof(data));
519 buffer_[size_ ++] = static_cast<uint8_t>((data & 0xff000000) >> 24);
520 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x00ff0000) >> 16);
521 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x0000ff00) >> 8);
522 buffer_[size_ ++] = static_cast<uint8_t>(data & 0x000000ff);
523 }
524
529 void writeUint64(uint64_t data) {
530 ensureAllocated(size_ + sizeof(data));
531 buffer_[size_ ++] = static_cast<uint8_t>((data & 0xff00000000000000) >> 56);
532 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x00ff000000000000) >> 48);
533 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x0000ff0000000000) >> 40);
534 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x000000ff00000000) >> 32);
535 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x00000000ff000000) >> 24);
536 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x0000000000ff0000) >> 16);
537 buffer_[size_ ++] = static_cast<uint8_t>((data & 0x000000000000ff00) >> 8);
538 buffer_[size_ ++] = static_cast<uint8_t>(data & 0x00000000000000ff);
539 }
540
547 void writeData(const void *data, size_t len) {
548 ensureAllocated(size_ + len);
549 static_cast<void>(std::memmove(buffer_ + size_, data, len));
550 size_ += len;
551 }
553
554private:
556 uint8_t* buffer_;
558 size_t size_;
560 size_t allocated_;
561
568 void ensureAllocated(size_t needed_size) {
569 if (allocated_ < needed_size) {
570 // Guess some bigger size
571 size_t new_size = (allocated_ == 0) ? 1024 : allocated_;
572 while (new_size < needed_size) {
573 new_size *= 2;
574 }
575 // Allocate bigger space. Note that buffer_ may be NULL,
576 // in which case realloc acts as malloc.
577 uint8_t* new_buffer_(static_cast<uint8_t*>(realloc(buffer_,
578 new_size)));
579 if (new_buffer_ == NULL) {
580 // If it fails, the original block is left intact by it
581 throw std::bad_alloc();
582 }
583 buffer_ = new_buffer_;
584 allocated_ = new_size;
585 }
586 }
587};
588
595typedef boost::shared_ptr<InputBuffer> InputBufferPtr;
596typedef boost::shared_ptr<OutputBuffer> OutputBufferPtr;
597
598} // namespace util
599} // namespace isc
600#endif // BUFFER_H
601
602// Local Variables:
603// mode: c++
604// 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
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:504
OutputBuffer & operator=(const OutputBuffer &other)
Assignment operator.
Definition: buffer.h:352
void wipe()
Wipe buffer content.
Definition: buffer.h:453
void writeUint8At(uint8_t data, size_t pos)
Write an unsigned 8-bit integer into the buffer.
Definition: buffer.h:476
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:529
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:463
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:487
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition: buffer.h:547
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:517
void trim(size_t len)
Trim the specified length of data from the end of the buffer.
Definition: buffer.h:438
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:426
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:448
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:595
boost::shared_ptr< OutputBuffer > OutputBufferPtr
Definition: buffer.h:596
Defines the logger used by the top-level component of kea-dhcp-ddns.