Branch data Line data Source code
1 : : // Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
2 : : //
3 : : // Permission to use, copy, modify, and/or distribute this software for any
4 : : // purpose with or without fee is hereby granted, provided that the above
5 : : // copyright notice and this permission notice appear in all copies.
6 : : //
7 : : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
8 : : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9 : : // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
10 : : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11 : : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
12 : : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13 : : // PERFORMANCE OF THIS SOFTWARE.
14 : :
15 : : #ifndef __BUFFER_H
16 : : #define __BUFFER_H 1
17 : :
18 : : #include <stdlib.h>
19 : : #include <cstring>
20 : : #include <vector>
21 : :
22 : : #include <stdint.h>
23 : :
24 : : #include <exceptions/exceptions.h>
25 : :
26 : : #include <boost/shared_ptr.hpp>
27 : :
28 : : namespace isc {
29 : : namespace util {
30 : :
31 : : ///
32 : : /// \brief A standard DNS module exception that is thrown if an out-of-range
33 : : /// buffer operation is being performed.
34 : : ///
35 : 66 : class InvalidBufferPosition : public Exception {
36 : : public:
37 : 12 : InvalidBufferPosition(const char* file, size_t line, const char* what) :
38 [ + - ][ + - ]: 66 : isc::Exception(file, line, what) {}
39 : : };
40 : :
41 : : ///\brief The \c InputBuffer class is a buffer abstraction for manipulating
42 : : /// read-only data.
43 : : ///
44 : : /// The main purpose of this class is to provide a safe placeholder for
45 : : /// examining wire-format data received from a network.
46 : : ///
47 : : /// Applications normally use this class only in a limited situation: as an
48 : : /// interface between legacy I/O operation (such as receiving data from a BSD
49 : : /// socket) and the rest of the BIND10 DNS library. One common usage of this
50 : : /// class for an application would therefore be something like this:
51 : : ///
52 : : /// \code unsigned char buf[1024];
53 : : /// struct sockaddr addr;
54 : : /// socklen_t addrlen = sizeof(addr);
55 : : /// int cc = recvfrom(s, buf, sizeof(buf), 0, &addr, &addrlen);
56 : : /// InputBuffer buffer(buf, cc);
57 : : /// // pass the buffer to a DNS message object to parse the message \endcode
58 : : ///
59 : : /// Other BIND10 DNS classes will then use methods of this class to get access
60 : : /// to the data, but the application normally doesn't have to care about the
61 : : /// details.
62 : : ///
63 : : /// An \c InputBuffer object internally holds a reference to the given data,
64 : : /// rather than make a local copy of the data. Also, it does not have an
65 : : /// ownership of the given data. It is application's responsibility to ensure
66 : : /// the data remains valid throughout the lifetime of the \c InputBuffer
67 : : /// object. Likewise, this object generally assumes the data isn't modified
68 : : /// throughout its lifetime; if the application modifies the data while this
69 : : /// object retains a reference to it, the result is undefined. The application
70 : : /// will also be responsible for releasing the data when it's not needed if it
71 : : /// was dynamically acquired.
72 : : ///
73 : : /// This is a deliberate design choice: although it's safer to make a local
74 : : /// copy of the given data on construction, it would cause unacceptable
75 : : /// performance overhead, especially considering that a DNS message can be
76 : : /// as large as a few KB. Alternatively, we could allow the object to allocate
77 : : /// memory internally and expose it to the application to store network data
78 : : /// in it. This is also a bad design, however, in that we would effectively
79 : : /// break the abstraction employed in the class, and do so by publishing
80 : : /// "read-only" stuff as a writable memory region. Since there doesn't seem to
81 : : /// be a perfect solution, we have adopted what we thought a "least bad" one.
82 : : ///
83 : : /// Methods for reading data from the buffer generally work like an input
84 : : /// stream: it begins with the head of the data, and once some length of data
85 : : /// is read from the buffer, the next read operation will take place from the
86 : : /// head of the unread data. An object of this class internally holds (a
87 : : /// notion of) where the next read operation should start. We call it the
88 : : /// <em>read position</em> in this document.
89 : : class InputBuffer {
90 : : public:
91 : : ///
92 : : /// \name Constructors and Destructor
93 : : //@{
94 : : /// \brief Constructor from variable length of data.
95 : : ///
96 : : /// It is caller's responsibility to ensure that the data is valid as long
97 : : /// as the buffer exists.
98 : : /// \param data A pointer to the data stored in the buffer.
99 : : /// \param len The length of the data in bytes.
100 : : InputBuffer(const void* data, size_t len) :
101 : 11407 : position_(0), data_(static_cast<const uint8_t*>(data)), len_(len) {}
102 : : //@}
103 : :
104 : : ///
105 : : /// \name Getter Methods
106 : : //@{
107 : : /// \brief Return the length of the data stored in the buffer.
108 : 0 : size_t getLength() const { return (len_); }
109 : : /// \brief Return the current read position.
110 : 0 : size_t getPosition() const { return (position_); }
111 : : //@}
112 : :
113 : : ///
114 : : /// \name Setter Methods
115 : : ///
116 : : //@{
117 : : /// \brief Set the read position of the buffer to the given value.
118 : : ///
119 : : /// The new position must be in the valid range of the buffer; otherwise
120 : : /// an exception of class \c isc::dns::InvalidBufferPosition will be thrown.
121 : : /// \param position The new position (offset from the beginning of the
122 : : /// buffer).
123 : 0 : void setPosition(size_t position) {
124 [ + + ][ - + ]: 6419 : if (position > len_) {
[ - + ][ - + ]
[ - + - + ]
[ # # ]
125 : 2 : throwError("position is too large");
126 : : }
127 : 270831 : position_ = position;
128 : 0 : }
129 : : //@}
130 : :
131 : : ///
132 : : /// \name Methods for reading data from the buffer.
133 : : //@{
134 : : /// \brief Read an unsigned 8-bit integer from the buffer and return it.
135 : : ///
136 : : /// If the remaining length of the buffer is smaller than 8-bit, an
137 : : /// exception of class \c isc::dns::InvalidBufferPosition will be thrown.
138 : 28197 : uint8_t readUint8() {
139 [ + + ]: 88360 : if (position_ + sizeof(uint8_t) > len_) {
140 : 8 : throwError("read beyond end of buffer");
141 : : }
142 : :
143 : 88352 : return (data_[position_++]);
144 : : }
145 : : /// \brief Read an unsigned 16-bit integer in network byte order from the
146 : : /// buffer, convert it to host byte order, and return it.
147 : : ///
148 : : /// If the remaining length of the buffer is smaller than 16-bit, an
149 : : /// exception of class \c isc::dns::InvalidBufferPosition will be thrown.
150 : 9729 : uint16_t readUint16() {
151 : : uint16_t data;
152 : : const uint8_t* cp;
153 : :
154 [ + + ][ + + ]: 272193 : if (position_ + sizeof(data) > len_) {
155 : 5 : throwError("read beyond end of buffer");
156 : : }
157 : :
158 : 272188 : cp = &data_[position_];
159 : 272188 : data = ((unsigned int)(cp[0])) << 8;
160 : 272188 : data |= ((unsigned int)(cp[1]));
161 : 272100 : position_ += sizeof(data);
162 : :
163 : 9728 : return (data);
164 : : }
165 : : /// \brief Read an unsigned 32-bit integer in network byte order from the
166 : : /// buffer, convert it to host byte order, and return it.
167 : : ///
168 : : /// If the remaining length of the buffer is smaller than 32-bit, an
169 : : /// exception of class \c isc::dns::InvalidBufferPosition will be thrown.
170 : 16121 : uint32_t readUint32() {
171 : : uint32_t data;
172 : : const uint8_t* cp;
173 : :
174 [ + + ]: 17064 : if (position_ + sizeof(data) > len_) {
175 : 2 : throwError("read beyond end of buffer");
176 : : }
177 : :
178 : 17062 : cp = &data_[position_];
179 : 17062 : data = ((unsigned int)(cp[0])) << 24;
180 : 17062 : data |= ((unsigned int)(cp[1])) << 16;
181 : 17062 : data |= ((unsigned int)(cp[2])) << 8;
182 : 17062 : data |= ((unsigned int)(cp[3]));
183 : 17062 : position_ += sizeof(data);
184 : :
185 : 16119 : return (data);
186 : : }
187 : : /// \brief Read data of the specified length from the buffer and copy it to
188 : : /// the caller supplied buffer.
189 : : ///
190 : : /// The data is copied as stored in the buffer; no conversion is performed.
191 : : /// If the remaining length of the buffer is smaller than the specified
192 : : /// length, an exception of class \c isc::dns::InvalidBufferPosition will
193 : : /// be thrown.
194 : 1617 : void readData(void* data, size_t len) {
195 [ + + ]: 1694 : if (position_ + len > len_) {
196 : 43 : throwError("read beyond end of buffer");
197 : : }
198 : :
199 : 1651 : std::memcpy(data, &data_[position_], len);
200 : 1651 : position_ += len;
201 : 1583 : }
202 : : //@}
203 : :
204 : : /// @brief Read specified number of bytes as a vector.
205 : : ///
206 : : /// If specified buffer is too short, it will be expanded
207 : : /// using vector::resize() method.
208 : : ///
209 : : /// @param Reference to a buffer (data will be stored there).
210 : : /// @param Size specified number of bytes to read in a vector.
211 : : ///
212 : 4 : void readVector(std::vector<uint8_t>& data, size_t len) {
213 [ + + ]: 4 : if (position_ + len > len_) {
214 : 1 : throwError("read beyond end of buffer");
215 : : }
216 : :
217 : : data.resize(len);
218 : 3 : readData(&data[0], len);
219 : 3 : }
220 : :
221 : : private:
222 : : /// \brief A common helper to throw an exception on invalid operation.
223 : : ///
224 : : /// Experiments showed that throwing from each method makes the buffer
225 : : /// operation slower, so we consolidate it here, and let the methods
226 : : /// call this.
227 : 61 : static void throwError(const char* msg) {
228 [ + - ][ + - ]: 122 : isc_throw(InvalidBufferPosition, msg);
229 : : }
230 : :
231 : : size_t position_;
232 : :
233 : : // XXX: The following must be private, but for a short term workaround with
234 : : // Boost.Python binding, we changed it to protected. We should soon
235 : : // revisit it.
236 : : protected:
237 : : const uint8_t* data_;
238 : : size_t len_;
239 : : };
240 : :
241 : : ///
242 : : ///\brief The \c OutputBuffer class is a buffer abstraction for manipulating
243 : : /// mutable data.
244 : : ///
245 : : /// The main purpose of this class is to provide a safe workplace for
246 : : /// constructing wire-format data to be sent out to a network. Here,
247 : : /// <em>safe</em> means that it automatically allocates necessary memory and
248 : : /// avoid buffer overrun.
249 : : ///
250 : : /// Like for the \c InputBuffer class, applications normally use this class only
251 : : /// in a limited situation. One common usage of this class for an application
252 : : /// would be something like this:
253 : : ///
254 : : /// \code OutputBuffer buffer(4096); // give a sufficiently large initial size
255 : : /// // pass the buffer to a DNS message object to construct a wire-format
256 : : /// // DNS message.
257 : : /// struct sockaddr to;
258 : : /// sendto(s, buffer.getData(), buffer.getLength(), 0, &to, sizeof(to));
259 : : /// \endcode
260 : : ///
261 : : /// where the \c getData() method gives a reference to the internal memory
262 : : /// region stored in the \c buffer object. This is a suboptimal design in that
263 : : /// it exposes an encapsulated "handle" of an object to its user.
264 : : /// Unfortunately, there is no easy way to avoid this without involving
265 : : /// expensive data copy if we want to use this object with a legacy API such as
266 : : /// a BSD socket interface. And, indeed, this is one major purpose for this
267 : : /// object. Applications should use this method only under such a special
268 : : /// circumstance. It should also be noted that the memory region returned by
269 : : /// \c getData() may be invalidated after a subsequent write operation.
270 : : ///
271 : : /// An \c OutputBuffer class object automatically extends its memory region when
272 : : /// data is written beyond the end of the current buffer. However, it will
273 : : /// involve performance overhead such as reallocating more memory and copying
274 : : /// data. It is therefore recommended to construct the buffer object with a
275 : : /// sufficiently large initial size.
276 : : /// The \c getCapacity() method provides the current maximum size of data
277 : : /// (including the portion already written) that can be written into the buffer
278 : : /// without causing memory reallocation.
279 : : ///
280 : : /// Methods for writing data into the buffer generally work like an output
281 : : /// stream: it begins with the head of the buffer, and once some length of data
282 : : /// is written into the buffer, the next write operation will take place from
283 : : /// the end of the buffer. Other methods to emulate "random access" are also
284 : : /// provided (e.g., \c writeUint16At()). The normal write operations are
285 : : /// normally exception-free as this class automatically extends the buffer
286 : : /// when necessary. However, in extreme cases such as an attempt of writing
287 : : /// multi-GB data, a separate exception (e.g., \c std::bad_alloc) may be thrown
288 : : /// by the system. This also applies to the constructor with a very large
289 : : /// initial size.
290 : : ///
291 : : /// Note to developers: it may make more sense to introduce an abstract base
292 : : /// class for the \c OutputBuffer and define the simple implementation as a
293 : : /// a concrete derived class. That way we can provide flexibility for future
294 : : /// extension such as more efficient buffer implementation or allowing users
295 : : /// to have their own customized version without modifying the source code.
296 : : /// We in fact considered that option, but at the moment chose the simpler
297 : : /// approach with a single concrete class because it may make the
298 : : /// implementation unnecessarily complicated while we were still not certain
299 : : /// if we really want that flexibility. We may revisit the class design as
300 : : /// we see more applications of the class. The same considerations apply to
301 : : /// the \c InputBuffer and \c MessageRenderer classes.
302 : : class OutputBuffer {
303 : : public:
304 : : ///
305 : : /// \name Constructors and Destructor
306 : : ///
307 : : //@{
308 : : /// \brief Constructor from the initial size of the buffer.
309 : : ///
310 : : /// \param len The initial length of the buffer in bytes.
311 : 4546 : OutputBuffer(size_t len) :
312 : : buffer_(NULL),
313 : : size_(0),
314 : 6450 : allocated_(len)
315 : : {
316 : : // We use malloc and free instead of C++ new[] and delete[].
317 : : // This way we can use realloc, which may in fact do it without a copy.
318 : 6450 : buffer_ = static_cast<uint8_t*>(malloc(allocated_));
319 [ + + ]: 4728 : if (buffer_ == NULL && len != 0) {
320 : 0 : throw std::bad_alloc();
321 : : }
322 : 4546 : }
323 : :
324 : : /// \brief Copy constructor
325 : 2 : OutputBuffer(const OutputBuffer& other) :
326 : : buffer_(NULL),
327 : : size_(other.size_),
328 : 2 : allocated_(other.allocated_)
329 : : {
330 : 2 : buffer_ = static_cast<uint8_t*>(malloc(allocated_));
331 [ - + ][ # # ]: 2 : if (buffer_ == NULL && allocated_ != 0) {
332 : 0 : throw std::bad_alloc();
333 : : }
334 : 2 : std::memcpy(buffer_, other.buffer_, size_);
335 : 2 : }
336 : :
337 : : /// \brief Destructor
338 : 0 : ~ OutputBuffer() {
339 : 6205 : free(buffer_);
340 : 0 : }
341 : : //@}
342 : :
343 : : /// \brief Assignment operator
344 : 2 : OutputBuffer& operator =(const OutputBuffer& other) {
345 : 20 : uint8_t* newbuff(static_cast<uint8_t*>(malloc(other.allocated_)));
346 [ - + ][ # # ]: 20 : if (newbuff == NULL && other.allocated_ != 0) {
347 : 0 : throw std::bad_alloc();
348 : : }
349 : 20 : free(buffer_);
350 : 20 : buffer_ = newbuff;
351 : 20 : size_ = other.size_;
352 : 20 : allocated_ = other.allocated_;
353 : 20 : std::memcpy(buffer_, other.buffer_, size_);
354 : 2 : return (*this);
355 : : }
356 : :
357 : : ///
358 : : /// \name Getter Methods
359 : : ///
360 : : //@{
361 : : /// \brief Return the current capacity of the buffer.
362 : 0 : size_t getCapacity() const { return (allocated_); }
363 : : /// \brief Return a pointer to the head of the data stored in the buffer.
364 : : ///
365 : : /// The caller can assume that the subsequent \c getLength() bytes are
366 : : /// identical to the stored data of the buffer.
367 : : ///
368 : : /// Note: The pointer returned by this method may be invalidated after a
369 : : /// subsequent write operation.
370 : 0 : const void* getData() const { return (buffer_); }
371 : : /// \brief Return the length of data written in the buffer.
372 : 0 : size_t getLength() const { return (size_); }
373 : : /// \brief Return the value of the buffer at the specified position.
374 : : ///
375 : : /// \c pos must specify the valid position of the buffer; otherwise an
376 : : /// exception class of \c InvalidBufferPosition will be thrown.
377 : : ///
378 : : /// \param pos The position in the buffer to be returned.
379 : 45224 : uint8_t operator[](size_t pos) const
380 : : {
381 [ - + ][ - + ]: 45296 : assert (pos < size_);
[ # # ]
382 : 45224 : return (buffer_[pos]);
383 : : }
384 : : //@}
385 : :
386 : : ///
387 : : /// \name Methods for writing data into the buffer.
388 : : ///
389 : : //@{
390 : : /// \brief Insert a specified length of gap at the end of the buffer.
391 : : ///
392 : : /// The caller should not assume any particular value to be inserted.
393 : : /// This method is provided as a shortcut to make a hole in the buffer
394 : : /// that is to be filled in later, e.g, by \ref writeUint16At().
395 : : /// \param len The length of the gap to be inserted in bytes.
396 : 710 : void skip(size_t len) {
397 : 1662 : ensureAllocated(size_ + len);
398 : 1662 : size_ += len;
399 : 710 : }
400 : :
401 : : /// \brief Trim the specified length of data from the end of the buffer.
402 : : ///
403 : : /// The specified length must not exceed the current data size of the
404 : : /// buffer; otherwise an exception of class \c isc::OutOfRange will
405 : : /// be thrown.
406 : : ///
407 : : /// \param len The length of data that should be trimmed.
408 : 25 : void trim(size_t len)
409 : : {
410 [ + + ]: 25 : if (len > size_) {
411 [ + - ][ # # ]: 2 : isc_throw(OutOfRange, "trimming too large from output buffer");
412 : : }
413 : 24 : size_ -= len;
414 : 24 : }
415 : : /// \brief Clear buffer content.
416 : : ///
417 : : /// This method can be used to re-initialize and reuse the buffer without
418 : : /// constructing a new one.
419 : 35 : void clear() { size_ = 0; }
420 : : /// \brief Write an unsigned 8-bit integer into the buffer.
421 : : ///
422 : : /// \param data The 8-bit integer to be written into the buffer.
423 : 80 : void writeUint8(uint8_t data) {
424 [ + - ]: 81 : ensureAllocated(size_ + 1);
425 : 81 : buffer_[size_ ++] = data;
426 : 80 : }
427 : :
428 : : /// \brief Write an unsigned 8-bit integer into the buffer.
429 : : ///
430 : : /// The position must be lower than the size of the buffer,
431 : : /// otherwise an exception of class \c isc::dns::InvalidBufferPosition
432 : : /// will be thrown.
433 : : ///
434 : : /// \param data The 8-bit integer to be written into the buffer.
435 : : /// \param pos The position in the buffer to write the data.
436 : 110 : void writeUint8At(uint8_t data, size_t pos) {
437 [ + + ]: 110 : if (pos + sizeof(data) > size_) {
438 [ + - ][ + - ]: 4 : isc_throw(InvalidBufferPosition, "write at invalid position");
439 : : }
440 : 108 : buffer_[pos] = data;
441 : 108 : }
442 : :
443 : : /// \brief Write an unsigned 16-bit integer in host byte order into the
444 : : /// buffer in network byte order.
445 : : ///
446 : : /// \param data The 16-bit integer to be written into the buffer.
447 : 6216 : void writeUint16(uint16_t data)
448 : : {
449 [ + - ][ + - ]: 139448 : ensureAllocated(size_ + sizeof(data));
450 : 139448 : buffer_[size_ ++] = static_cast<uint8_t>((data & 0xff00U) >> 8);
451 : 139448 : buffer_[size_ ++] = static_cast<uint8_t>(data & 0x00ffU);
452 : 6216 : }
453 : : /// \brief Write an unsigned 16-bit integer in host byte order at the
454 : : /// specified position of the buffer in network byte order.
455 : : ///
456 : : /// The buffer must have a sufficient room to store the given data at the
457 : : /// given position, that is, <code>pos + 2 < getLength()</code>;
458 : : /// otherwise an exception of class \c isc::dns::InvalidBufferPosition will
459 : : /// be thrown.
460 : : /// Note also that this method never extends the buffer.
461 : : ///
462 : : /// \param data The 16-bit integer to be written into the buffer.
463 : : /// \param pos The beginning position in the buffer to write the data.
464 : 6367 : void writeUint16At(uint16_t data, size_t pos)
465 : : {
466 [ + + ]: 6367 : if (pos + sizeof(data) > size_) {
467 [ + - ][ + - ]: 6 : isc_throw(InvalidBufferPosition, "write at invalid position");
468 : : }
469 : :
470 : 6364 : buffer_[pos] = static_cast<uint8_t>((data & 0xff00U) >> 8);
471 : 6364 : buffer_[pos + 1] = static_cast<uint8_t>(data & 0x00ffU);
472 : 6364 : }
473 : : /// \brief Write an unsigned 32-bit integer in host byte order
474 : : /// into the buffer in network byte order.
475 : : ///
476 : : /// \param data The 32-bit integer to be written into the buffer.
477 : 16693 : void writeUint32(uint32_t data)
478 : : {
479 : 16696 : ensureAllocated(size_ + sizeof(data));
480 : 16696 : buffer_[size_ ++] = static_cast<uint8_t>((data & 0xff000000) >> 24);
481 : 16696 : buffer_[size_ ++] = static_cast<uint8_t>((data & 0x00ff0000) >> 16);
482 : 16696 : buffer_[size_ ++] = static_cast<uint8_t>((data & 0x0000ff00) >> 8);
483 : 16696 : buffer_[size_ ++] = static_cast<uint8_t>(data & 0x000000ff);
484 : 16693 : }
485 : : /// \brief Copy an arbitrary length of data into the buffer.
486 : : ///
487 : : /// No conversion on the copied data is performed.
488 : : ///
489 : : /// \param data A pointer to the data to be copied into the buffer.
490 : : /// \param len The length of the data in bytes.
491 : 1992 : void writeData(const void *data, size_t len)
492 : : {
493 [ + - ]: 136413 : ensureAllocated(size_ + len);
494 : 136413 : std::memcpy(buffer_ + size_, data, len);
495 : 136413 : size_ += len;
496 : 1992 : }
497 : : //@}
498 : :
499 : : private:
500 : : // The actual data
501 : : uint8_t* buffer_;
502 : : // How many bytes are used
503 : : size_t size_;
504 : : // How many bytes do we have preallocated (eg. the capacity)
505 : : size_t allocated_;
506 : : // Make sure at last needed_size bytes are allocated in the buffer
507 : 25348 : void ensureAllocated(size_t needed_size) {
508 [ + + ][ + + ]: 294300 : if (allocated_ < needed_size) {
[ + + ][ # # ]
[ # # ]
509 : : // Guess some bigger size
510 [ + + ][ # # ]: 1187 : size_t new_size = (allocated_ == 0) ? 1024 : allocated_;
[ # # ][ + + ]
511 [ + + ][ + + ]: 1492 : while (new_size < needed_size) {
[ # # ][ # # ]
[ # # ]
512 : 305 : new_size *= 2;
513 : : }
514 : : // Allocate bigger space
515 : : uint8_t* new_buffer_(static_cast<uint8_t*>(realloc(buffer_,
516 : 1187 : new_size)));
517 [ - + ][ - + ]: 1187 : if (new_buffer_ == NULL) {
[ # # ]
518 : : // If it fails, the original block is left intact by it
519 : 0 : throw std::bad_alloc();
520 : : }
521 : 1187 : buffer_ = new_buffer_;
522 : 1187 : allocated_ = new_size;
523 : : }
524 : 25348 : }
525 : : };
526 : :
527 : : /// \brief Pointer-like types pointing to \c InputBuffer or \c OutputBuffer
528 : : ///
529 : : /// These types are expected to be used as an argument in asynchronous
530 : : /// callback functions. The internal reference-counting will ensure that
531 : : /// that ongoing state information will not be lost if the object
532 : : /// that originated the asynchronous call falls out of scope.
533 : : typedef boost::shared_ptr<InputBuffer> InputBufferPtr;
534 : : typedef boost::shared_ptr<OutputBuffer> OutputBufferPtr;
535 : :
536 : : } // namespace util
537 : : } // namespace isc
538 : : #endif // __BUFFER_H
539 : :
540 : : // Local Variables:
541 : : // mode: c++
542 : : // End:
|