0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-19 19:52:15 +02:00

Buffer: Prepare to decouple allocated buffer / RC

Rename BufferAllocated --> BufferAllocatedRc

Buffer: split RC from BufferAllocated
Also make changes as needed where BufferAllocated is used

Buffer: Split allocation flags into own struct
Leaving flags in template causes each alias to have identical flags
by different names, which requires each type to pointlessly use
the nested name.

Make RC: Clean up headers buffer.hpp, make_rc.hpp

Signed-off-by: Charlie Vigue <charlie.vigue@openvpn.com>
This commit is contained in:
Charlie Vigue 2024-09-09 13:47:13 +00:00 committed by Jenkins-dev
parent 5ce80fc300
commit ef8da98bd4
56 changed files with 383 additions and 206 deletions

View File

@ -442,7 +442,7 @@ Here is a brief set of guidelines:
rather than a :code:`char *`. rather than a :code:`char *`.
* When dealing with binary data or buffers, always try to use a * When dealing with binary data or buffers, always try to use a
:code:`Buffer`, :code:`ConstBuffer`, :code:`BufferAllocated`, or :code:`Buffer`, :code:`ConstBuffer`, :code:`BufferAllocatedRc`, or
:code:`BufferPtr` object to provide managed access to the buffer, to :code:`BufferPtr` object to provide managed access to the buffer, to
protect against security bugs that arise when using raw buffer pointers. protect against security bugs that arise when using raw buffer pointers.
See `<openvpn/buffer/buffer.hpp>`_ for the OpenVPN :code:`Buffer` classes. See `<openvpn/buffer/buffer.hpp>`_ for the OpenVPN :code:`Buffer` classes.

View File

@ -32,7 +32,7 @@
namespace openvpn::CF { namespace openvpn::CF {
// essentially a vector of void *, used as source for array and dictionary constructors // essentially a vector of void *, used as source for array and dictionary constructors
typedef BufferAllocatedType<CFTypeRef, thread_unsafe_refcount> SrcList; typedef BufferAllocatedType<CFTypeRef> SrcList;
inline Array array(const SrcList &values) inline Array array(const SrcList &values)
{ {

View File

@ -45,7 +45,7 @@
// Buffer : a simple buffer of unsigned char without ownership semantics // Buffer : a simple buffer of unsigned char without ownership semantics
// ConstBuffer : like buffer but where the data pointed to by the buffer is read-only // ConstBuffer : like buffer but where the data pointed to by the buffer is read-only
// BufferAllocated : an allocated Buffer with ownership semantics // BufferAllocated : an allocated Buffer with ownership semantics
// BufferPtr : a smart, reference-counted pointer to a BufferAllocated // BufferPtr : a smart, reference-counted pointer to a BufferAllocatedRc
#pragma once #pragma once
@ -63,6 +63,7 @@
#include <openvpn/common/exception.hpp> #include <openvpn/common/exception.hpp>
#include <openvpn/common/rc.hpp> #include <openvpn/common/rc.hpp>
#include <openvpn/buffer/bufclamp.hpp> #include <openvpn/buffer/bufclamp.hpp>
#include <openvpn/common/make_rc.hpp>
#ifdef OPENVPN_BUFFER_ABORT #ifdef OPENVPN_BUFFER_ABORT
#define OPENVPN_BUFFER_THROW(exc) \ #define OPENVPN_BUFFER_THROW(exc) \
@ -204,7 +205,7 @@ class BufferException : public std::exception
// =============================================================================================== // ===============================================================================================
// =============================================================================================== // ===============================================================================================
template <typename T, typename R> template <typename T>
class BufferAllocatedType; class BufferAllocatedType;
template <typename T> template <typename T>
@ -868,12 +869,24 @@ class BufferType : public ConstBufferType<T>
// class BufferAllocatedType // class BufferAllocatedType
// =============================================================================================== // ===============================================================================================
template <typename T, typename R> // Allocation and security for the buffer
class BufferAllocatedType : public BufferType<T>, public RC<R> struct BufAllocFlags
{
enum
{
CONSTRUCT_ZERO = (1 << 0), ///< if enabled, constructors/init will zero allocated space
DESTRUCT_ZERO = (1 << 1), ///< if enabled, destructor will zero data before deletion
GROW = (1 << 2), ///< if enabled, buffer will grow (otherwise buffer_full exception will be thrown)
ARRAY = (1 << 3), ///< if enabled, use as array
};
};
template <typename T>
class BufferAllocatedType : public BufferType<T>
{ {
private: private:
// Friend to all specializations of this template allows access to other.data_ // Friend to all specializations of this template allows access to other.data_
template <typename, typename> template <typename>
friend class BufferAllocatedType; friend class BufferAllocatedType;
public: public:
@ -888,14 +901,6 @@ class BufferAllocatedType : public BufferType<T>, public RC<R>
using BufferType<T>::c_data; using BufferType<T>::c_data;
using BufferType<T>::swap; using BufferType<T>::swap;
enum
{
CONSTRUCT_ZERO = (1 << 0), ///< if enabled, constructors/init will zero allocated space
DESTRUCT_ZERO = (1 << 1), ///< if enabled, destructor will zero data before deletion
GROW = (1 << 2), ///< if enabled, buffer will grow (otherwise buffer_full exception will be thrown)
ARRAY = (1 << 3), ///< if enabled, use as array
};
/** /**
* @brief Default constructor. * @brief Default constructor.
*/ */
@ -979,14 +984,8 @@ class BufferAllocatedType : public BufferType<T>, public RC<R>
* @tparam R_ The template parameter type of the other BufferAllocatedType object. * @tparam R_ The template parameter type of the other BufferAllocatedType object.
* @param other The other BufferAllocatedType object to move from. * @param other The other BufferAllocatedType object to move from.
*/ */
template <typename T_, typename R_> template <typename T_>
void move(BufferAllocatedType<T_, R_> &other); void move(BufferAllocatedType<T_> &other);
/**
* @brief Moves the contents of this BufferAllocatedType object into a new RCPtr object.
* @return A new RCPtr object containing the contents of this BufferAllocatedType object.
*/
RCPtr<BufferAllocatedType<T, R>> move_to_ptr();
/** /**
* @brief Swaps the contents of this BufferAllocatedType object with another BufferAllocatedType object. * @brief Swaps the contents of this BufferAllocatedType object with another BufferAllocatedType object.
@ -994,8 +993,8 @@ class BufferAllocatedType : public BufferType<T>, public RC<R>
* @tparam R_ The template parameter type of the other BufferAllocatedType object. * @tparam R_ The template parameter type of the other BufferAllocatedType object.
* @param other The other BufferAllocatedType object to swap with. * @param other The other BufferAllocatedType object to swap with.
*/ */
template <typename T_, typename R_> template <typename T_>
void swap(BufferAllocatedType<T_, R_> &other); void swap(BufferAllocatedType<T_> &other);
/** /**
* @brief Move constructor. * @brief Move constructor.
@ -1003,8 +1002,8 @@ class BufferAllocatedType : public BufferType<T>, public RC<R>
* @tparam R_ The template parameter type of the other BufferAllocatedType object. * @tparam R_ The template parameter type of the other BufferAllocatedType object.
* @param other The other BufferAllocatedType object to move from. * @param other The other BufferAllocatedType object to move from.
*/ */
template <typename T_, typename R_> template <typename T_>
BufferAllocatedType(BufferAllocatedType<T_, R_> &&other) noexcept; BufferAllocatedType(BufferAllocatedType<T_> &&other) noexcept;
/** /**
* @brief Move assignment operator. * @brief Move assignment operator.
@ -1641,48 +1640,48 @@ ConstBufferType<T>::ConstBufferType(const U *data, const size_t offset, const si
: ConstBufferType(const_cast<U *>(data), offset, size, capacity){}; : ConstBufferType(const_cast<U *>(data), offset, size, capacity){};
// =============================================================================================== // ===============================================================================================
// BufferAllocatedType<T, R> member function definitions // BufferAllocatedType<T> member function definitions
// =============================================================================================== // ===============================================================================================
template <typename T, typename R> template <typename T>
BufferAllocatedType<T, R>::BufferAllocatedType(const size_t offset, const size_t size, const size_t capacity, const unsigned int flags) BufferAllocatedType<T>::BufferAllocatedType(const size_t offset, const size_t size, const size_t capacity, const unsigned int flags)
: BufferType<T>(capacity ? new T[capacity] : nullptr, offset, size, capacity), flags_(flags) : BufferType<T>(capacity ? new T[capacity] : nullptr, offset, size, capacity), flags_(flags)
{ {
if (flags & CONSTRUCT_ZERO) if (flags & BufAllocFlags::CONSTRUCT_ZERO)
std::memset(data_raw(), 0, capacity * sizeof(T)); std::memset(data_raw(), 0, capacity * sizeof(T));
} }
template <typename T, typename R> template <typename T>
BufferAllocatedType<T, R>::BufferAllocatedType() BufferAllocatedType<T>::BufferAllocatedType()
: BufferAllocatedType(0, 0, 0, 0) : BufferAllocatedType(0, 0, 0, 0)
{ {
static_assert(std::is_nothrow_move_constructible_v<BufferAllocatedType>, static_assert(std::is_nothrow_move_constructible_v<BufferAllocatedType>,
"class BufferAllocatedType not noexcept move constructable"); "class BufferAllocatedType not noexcept move constructable");
} }
template <typename T, typename R> template <typename T>
BufferAllocatedType<T, R>::BufferAllocatedType(const size_t capacity, const unsigned int flags) BufferAllocatedType<T>::BufferAllocatedType(const size_t capacity, const unsigned int flags)
: BufferAllocatedType(0, flags & ARRAY ? capacity : 0, capacity, flags){}; : BufferAllocatedType(0, flags & BufAllocFlags::ARRAY ? capacity : 0, capacity, flags){};
template <typename T, typename R> template <typename T>
BufferAllocatedType<T, R>::BufferAllocatedType(const T *data, const size_t size, const unsigned int flags) BufferAllocatedType<T>::BufferAllocatedType(const T *data, const size_t size, const unsigned int flags)
: BufferAllocatedType(0, size, size, flags) : BufferAllocatedType(0, size, size, flags)
{ {
if (size) if (size && data)
std::memcpy(data_raw(), data, size * sizeof(T)); std::memcpy(data_raw(), data, size * sizeof(T));
} }
template <typename T, typename R> template <typename T>
BufferAllocatedType<T, R>::BufferAllocatedType(const BufferAllocatedType &other) BufferAllocatedType<T>::BufferAllocatedType(const BufferAllocatedType &other)
: BufferAllocatedType(other.offset(), other.size(), other.capacity(), other.flags_) : BufferAllocatedType(other.offset(), other.size(), other.capacity(), other.flags_)
{ {
if (size()) if (size())
std::memcpy(data(), other.c_data(), size() * sizeof(T)); std::memcpy(data(), other.c_data(), size() * sizeof(T));
} }
template <typename T, typename R> template <typename T>
template <typename T_> template <typename T_>
BufferAllocatedType<T, R>::BufferAllocatedType(const BufferType<T_> &other, const unsigned int flags) BufferAllocatedType<T>::BufferAllocatedType(const BufferType<T_> &other, const unsigned int flags)
: BufferAllocatedType(other.offset(), other.size(), other.capacity(), flags) : BufferAllocatedType(other.offset(), other.size(), other.capacity(), flags)
{ {
static_assert(sizeof(T) == sizeof(T_), "size inconsistency"); static_assert(sizeof(T) == sizeof(T_), "size inconsistency");
@ -1690,8 +1689,8 @@ BufferAllocatedType<T, R>::BufferAllocatedType(const BufferType<T_> &other, cons
std::memcpy(data(), other.c_data(), size() * sizeof(T)); std::memcpy(data(), other.c_data(), size() * sizeof(T));
} }
template <typename T, typename R> template <typename T>
void BufferAllocatedType<T, R>::operator=(const BufferAllocatedType &other) void BufferAllocatedType<T>::operator=(const BufferAllocatedType &other)
{ {
if (this != &other) if (this != &other)
{ {
@ -1702,74 +1701,68 @@ void BufferAllocatedType<T, R>::operator=(const BufferAllocatedType &other)
} }
} }
template <typename T, typename R> template <typename T>
void BufferAllocatedType<T, R>::init(const size_t capacity, const unsigned int flags) void BufferAllocatedType<T>::init(const size_t capacity, const unsigned int flags)
{ {
auto tempBuffer = BufferAllocatedType(capacity, flags); auto tempBuffer = BufferAllocatedType(capacity, flags);
swap(tempBuffer); swap(tempBuffer);
} }
template <typename T, typename R> template <typename T>
void BufferAllocatedType<T, R>::init(const T *data, const size_t size, const unsigned int flags) void BufferAllocatedType<T>::init(const T *data, const size_t size, const unsigned int flags)
{ {
auto tempBuffer = BufferAllocatedType(data, size, flags); auto tempBuffer = BufferAllocatedType(data, size, flags);
swap(tempBuffer); swap(tempBuffer);
} }
template <typename T, typename R> template <typename T>
void BufferAllocatedType<T, R>::realloc(const size_t newcap) void BufferAllocatedType<T>::realloc(const size_t newcap)
{ {
if (newcap > capacity()) if (newcap > capacity())
realloc_(newcap); realloc_(newcap);
} }
template <typename T, typename R> template <typename T>
void BufferAllocatedType<T, R>::reset(const size_t min_capacity, const unsigned int flags) void BufferAllocatedType<T>::reset(const size_t min_capacity, const unsigned int flags)
{ {
if (min_capacity > capacity()) if (min_capacity > capacity())
init(min_capacity, flags); init(min_capacity, flags);
} }
template <typename T, typename R> template <typename T>
void BufferAllocatedType<T, R>::reset(const size_t headroom, const size_t min_capacity, const unsigned int flags) void BufferAllocatedType<T>::reset(const size_t headroom, const size_t min_capacity, const unsigned int flags)
{ {
reset(min_capacity, flags); reset(min_capacity, flags);
init_headroom(headroom); init_headroom(headroom);
} }
template <typename T, typename R> template <typename T>
template <typename T_, typename R_> template <typename T_>
void BufferAllocatedType<T, R>::move(BufferAllocatedType<T_, R_> &other) void BufferAllocatedType<T>::move(BufferAllocatedType<T_> &other)
{ {
auto temp = BufferAllocatedType(); auto temp = BufferAllocatedType();
swap(other); swap(other);
other.swap(temp); other.swap(temp);
} }
template <typename T, typename R> template <typename T>
RCPtr<BufferAllocatedType<T, R>> BufferAllocatedType<T, R>::move_to_ptr() template <typename T_>
{ void BufferAllocatedType<T>::swap(BufferAllocatedType<T_> &other)
return RCPtr<BufferAllocatedType<T, R>>(new BufferAllocatedType<T, R>(std::move(*this)));
}
template <typename T, typename R>
template <typename T_, typename R_>
void BufferAllocatedType<T, R>::swap(BufferAllocatedType<T_, R_> &other)
{ {
BufferType<T>::swap(other); BufferType<T>::swap(other);
std::swap(flags_, other.flags_); std::swap(flags_, other.flags_);
} }
template <typename T, typename R> template <typename T>
template <typename T_, typename R_> template <typename T_>
BufferAllocatedType<T, R>::BufferAllocatedType(BufferAllocatedType<T_, R_> &&other) noexcept BufferAllocatedType<T>::BufferAllocatedType(BufferAllocatedType<T_> &&other) noexcept
: BufferAllocatedType() : BufferAllocatedType()
{ {
move(other); move(other);
} }
template <typename T, typename R> template <typename T>
BufferAllocatedType<T, R> &BufferAllocatedType<T, R>::operator=(BufferAllocatedType &&other) noexcept BufferAllocatedType<T> &BufferAllocatedType<T>::operator=(BufferAllocatedType &&other) noexcept
{ {
if (this != &other) if (this != &other)
{ {
@ -1778,53 +1771,53 @@ BufferAllocatedType<T, R> &BufferAllocatedType<T, R>::operator=(BufferAllocatedT
return *this; return *this;
} }
template <typename T, typename R> template <typename T>
void BufferAllocatedType<T, R>::clear() void BufferAllocatedType<T>::clear()
{ {
auto tempBuffer = BufferAllocatedType(0, 0, 0, 0); auto tempBuffer = BufferAllocatedType(0, 0, 0, 0);
swap(tempBuffer); swap(tempBuffer);
} }
template <typename T, typename R> template <typename T>
void BufferAllocatedType<T, R>::or_flags(const unsigned int flags) void BufferAllocatedType<T>::or_flags(const unsigned int flags)
{ {
flags_ |= flags; flags_ |= flags;
} }
template <typename T, typename R> template <typename T>
void BufferAllocatedType<T, R>::and_flags(const unsigned int flags) void BufferAllocatedType<T>::and_flags(const unsigned int flags)
{ {
flags_ &= flags; flags_ &= flags;
} }
template <typename T, typename R> template <typename T>
BufferAllocatedType<T, R>::~BufferAllocatedType() BufferAllocatedType<T>::~BufferAllocatedType()
{ {
if (data_raw()) if (data_raw())
free_data(); free_data();
} }
template <typename T, typename R> template <typename T>
void BufferAllocatedType<T, R>::reset_impl(const size_t min_capacity, const unsigned int flags) void BufferAllocatedType<T>::reset_impl(const size_t min_capacity, const unsigned int flags)
{ {
init(min_capacity, flags); init(min_capacity, flags);
} }
template <typename T, typename R> template <typename T>
void BufferAllocatedType<T, R>::resize(const size_t new_capacity) void BufferAllocatedType<T>::resize(const size_t new_capacity)
{ {
const size_t newcap = std::max(new_capacity, capacity() * 2); const size_t newcap = std::max(new_capacity, capacity() * 2);
if (newcap > capacity()) if (newcap > capacity())
{ {
if (flags_ & GROW) if (flags_ & BufAllocFlags::GROW)
realloc_(newcap); realloc_(newcap);
else else
buffer_full_error(newcap, true); buffer_full_error(newcap, true);
} }
} }
template <typename T, typename R> template <typename T>
void BufferAllocatedType<T, R>::realloc_(const size_t newcap) void BufferAllocatedType<T>::realloc_(const size_t newcap)
{ {
auto tempBuffer = BufferAllocatedType(offset(), size(), newcap, flags_); auto tempBuffer = BufferAllocatedType(offset(), size(), newcap, flags_);
if (size()) if (size())
@ -1832,10 +1825,10 @@ void BufferAllocatedType<T, R>::realloc_(const size_t newcap)
swap(tempBuffer); swap(tempBuffer);
} }
template <typename T, typename R> template <typename T>
void BufferAllocatedType<T, R>::free_data() void BufferAllocatedType<T>::free_data()
{ {
if (size() && (flags_ & DESTRUCT_ZERO)) if (size() && (flags_ & BufAllocFlags::DESTRUCT_ZERO))
std::memset(data_raw(), 0, capacity() * sizeof(T)); std::memset(data_raw(), 0, capacity() * sizeof(T));
delete[] data_raw(); delete[] data_raw();
} }
@ -1844,17 +1837,18 @@ void BufferAllocatedType<T, R>::free_data()
// specializations of BufferType for unsigned char // specializations of BufferType for unsigned char
// =============================================================================================== // ===============================================================================================
typedef BufferType<unsigned char> Buffer; using Buffer = BufferType<unsigned char>;
typedef ConstBufferType<unsigned char> ConstBuffer; using ConstBuffer = ConstBufferType<unsigned char>;
typedef BufferAllocatedType<unsigned char, thread_unsafe_refcount> BufferAllocated; using BufferAllocated = BufferAllocatedType<unsigned char>;
typedef RCPtr<BufferAllocated> BufferPtr; using BufferAllocatedRc = RcEnable<BufferAllocated, RC<thread_unsafe_refcount>>;
using BufferPtr = RCPtr<BufferAllocatedRc>;
// =============================================================================================== // ===============================================================================================
// BufferAllocated with thread-safe refcount // BufferAllocated + RC with thread-safe refcount
// =============================================================================================== // ===============================================================================================
typedef BufferAllocatedType<unsigned char, thread_safe_refcount> BufferAllocatedTS; using BufferAllocatedTS = RcEnable<BufferAllocated, RC<thread_safe_refcount>>;
typedef RCPtr<BufferAllocatedTS> BufferPtrTS; using BufferPtrTS = RCPtr<BufferAllocatedTS>;
// =============================================================================================== // ===============================================================================================
// cast BufferType<T> to ConstBufferType<T> // cast BufferType<T> to ConstBufferType<T>

View File

@ -56,7 +56,7 @@ struct BufferCollection : public COLLECTION<BufferPtr>
const size_t size = join_size(); const size_t size = join_size();
// allocate buffer // allocate buffer
BufferPtr big = new BufferAllocated(size + headroom + tailroom, 0); auto big = BufferAllocatedRc::Create(size + headroom + tailroom, 0);
big->init_headroom(headroom); big->init_headroom(headroom);
// second pass -- copy data // second pass -- copy data
@ -89,7 +89,7 @@ struct BufferCollection : public COLLECTION<BufferPtr>
{ {
BufferCollection ret; BufferCollection ret;
for (auto &b : *this) for (auto &b : *this)
ret.emplace_back(new BufferAllocated(*b)); ret.emplace_back(BufferAllocatedRc::Create(*b));
return ret; return ret;
} }
@ -111,7 +111,7 @@ struct BufferCollection : public COLLECTION<BufferPtr>
return; return;
} }
} }
emplace_back(new BufferAllocated(std::move(buf))); emplace_back(BufferAllocatedRc::Create(std::move(buf)));
} }
}; };

View File

@ -56,7 +56,7 @@ inline void buf_write_string(Buffer &buf, const char *str)
inline BufferPtr buf_from_string(const std::string &str) inline BufferPtr buf_from_string(const std::string &str)
{ {
const size_t len = str.length(); const size_t len = str.length();
BufferPtr buf(new BufferAllocated(len, 0)); BufferPtr buf = BufferAllocatedRc::Create(len, 0);
buf->write((unsigned char *)str.c_str(), len); buf->write((unsigned char *)str.c_str(), len);
return buf; return buf;
} }
@ -65,7 +65,7 @@ inline BufferPtr buf_from_string(const std::string &str)
inline BufferPtr buf_from_string(const char *str) inline BufferPtr buf_from_string(const char *str)
{ {
const size_t len = std::strlen(str); const size_t len = std::strlen(str);
BufferPtr buf(new BufferAllocated(len, 0)); BufferPtr buf = BufferAllocatedRc::Create(len, 0);
buf->write((unsigned char *)str, len); buf->write((unsigned char *)str, len);
return buf; return buf;
} }

View File

@ -45,7 +45,7 @@ inline BufferPtr compress(const ConstBuffer &src,
OPENVPN_THROW(lz4_error, "compress buffer size=" << src.size() << " exceeds LZ4_MAX_INPUT_SIZE=" << LZ4_MAX_INPUT_SIZE); OPENVPN_THROW(lz4_error, "compress buffer size=" << src.size() << " exceeds LZ4_MAX_INPUT_SIZE=" << LZ4_MAX_INPUT_SIZE);
// allocate dest buffer // allocate dest buffer
BufferPtr dest = new BufferAllocated(sizeof(std::uint32_t) + headroom + tailroom + LZ4_COMPRESSBOUND(src.size()), 0); auto dest = BufferAllocatedRc::Create(sizeof(std::uint32_t) + headroom + tailroom + LZ4_COMPRESSBOUND(src.size()), 0);
dest->init_headroom(headroom); dest->init_headroom(headroom);
// as a hint to receiver, write the decompressed size // as a hint to receiver, write the decompressed size
@ -83,7 +83,7 @@ inline BufferPtr decompress(const ConstBuffer &source,
OPENVPN_THROW(lz4_error, "decompress expansion size=" << size << " is too large (must be <= " << max_decompressed_size << ')'); OPENVPN_THROW(lz4_error, "decompress expansion size=" << size << " is too large (must be <= " << max_decompressed_size << ')');
// allocate dest buffer // allocate dest buffer
BufferPtr dest = new BufferAllocated(headroom + tailroom + size, 0); auto dest = BufferAllocatedRc::Create(headroom + tailroom + size, 0);
dest->init_headroom(headroom); dest->init_headroom(headroom);
// decompress // decompress

View File

@ -30,10 +30,13 @@
#include <openvpn/buffer/bufstr.hpp> #include <openvpn/buffer/bufstr.hpp>
namespace openvpn { namespace openvpn {
/**
@brief A string-like type that clears the buffer contents on delete
*/
class SafeString class SafeString
{ {
static constexpr size_t INITIAL_CAPACITY = 32; static constexpr size_t INITIAL_CAPACITY = 32;
static constexpr unsigned int BUF_FLAGS = BufferAllocated::DESTRUCT_ZERO | BufferAllocated::GROW; static constexpr unsigned int BUF_FLAGS = BufAllocFlags::DESTRUCT_ZERO | BufAllocFlags::GROW;
public: public:
SafeString() SafeString()

View File

@ -90,7 +90,7 @@ inline BufferPtr compress_gzip(BufferPtr src,
if (status != Z_OK) if (status != Z_OK)
OPENVPN_THROW(zlib_error, "zlib deflateinit2 failed, error=" << status); OPENVPN_THROW(zlib_error, "zlib deflateinit2 failed, error=" << status);
const uLong outcap = ::deflateBound(&zs.s, src->size()); const uLong outcap = ::deflateBound(&zs.s, src->size());
BufferPtr b = new BufferAllocated(outcap + headroom + tailroom, 0); auto b = BufferAllocatedRc::Create(outcap + headroom + tailroom, 0);
b->init_headroom(headroom); b->init_headroom(headroom);
zs.s.next_out = b->data(); zs.s.next_out = b->data();
zs.s.avail_out = numeric_cast<decltype(zs.s.avail_out)>(outcap); zs.s.avail_out = numeric_cast<decltype(zs.s.avail_out)>(outcap);
@ -138,7 +138,7 @@ inline BufferPtr decompress_gzip(BufferPtr src,
{ {
// use headroom/tailroom on first block to take advantage // use headroom/tailroom on first block to take advantage
// of BufferList::join() optimization for one-block lists // of BufferList::join() optimization for one-block lists
BufferPtr b = new BufferAllocated(block_size + hr + tr, 0); auto b = BufferAllocatedRc::Create(block_size + hr + tr, 0);
b->init_headroom(hr); b->init_headroom(hr);
const size_t avail = b->remaining(tr); const size_t avail = b->remaining(tr);
zs.s.next_out = b->data(); zs.s.next_out = b->data();

View File

@ -132,9 +132,9 @@ inline AccHandshaker::MsgT AccHandshaker::process_msg(const MsgT &msg)
auto &api = mSslApi->get(); auto &api = mSslApi->get();
if (msg) if (msg)
{ {
api.write_ciphertext(new BufferAllocated(reinterpret_cast<const unsigned char *>(msg->c_str()), api.write_ciphertext(BufferAllocatedRc::Create(reinterpret_cast<const unsigned char *>(msg->c_str()),
msg->size(), msg->size(),
0)); 0));
// Won't handshake without this even though there is no data available. // Won't handshake without this even though there is no data available.
uint8_t cleartext[8]; uint8_t cleartext[8];

View File

@ -416,7 +416,7 @@ struct InfoJSON : public Base
virtual std::string render() const virtual std::string render() const
{ {
BufferAllocated buf(512, BufferAllocated::GROW); BufferAllocated buf(512, BufAllocFlags::GROW);
buf_append_string(buf, msg_type); buf_append_string(buf, msg_type);
buf_append_string(buf, ":"); buf_append_string(buf, ":");
json::format_compact(jdata, buf); json::format_compact(jdata, buf);

View File

@ -86,7 +86,7 @@ inline BufferPtr read_binary(const std::string &filename,
ifs.seekg(0, std::ios::beg); ifs.seekg(0, std::ios::beg);
// allocate buffer // allocate buffer
BufferPtr b = new BufferAllocated(size_t(length), buffer_flags | BufferAllocated::ARRAY); auto b = BufferAllocatedRc::Create(size_t(length), buffer_flags | BufAllocFlags::ARRAY);
// read data // read data
ifs.read((char *)b->data(), length); ifs.read((char *)b->data(), length);
@ -114,7 +114,7 @@ inline BufferPtr read_binary_linear(const std::string &filename,
std::streamsize total_size = 0; std::streamsize total_size = 0;
while (true) while (true)
{ {
BufferPtr b = new BufferAllocated(block_size, 0); auto b = BufferAllocatedRc::Create(block_size, 0);
ifs.read((char *)b->data(), b->remaining()); ifs.read((char *)b->data(), b->remaining());
const std::streamsize size = ifs.gcount(); const std::streamsize size = ifs.gcount();
if (size) if (size)

View File

@ -161,7 +161,7 @@ inline BufferPtr read_binary_unix(const std::string &fn,
throw file_unix_error(fn + " : file too large [" + std::to_string(length) + '/' + std::to_string(max_size) + ']'); throw file_unix_error(fn + " : file too large [" + std::to_string(length) + '/' + std::to_string(max_size) + ']');
// allocate buffer // allocate buffer
BufferPtr bp = new BufferAllocated(size_t(length), buffer_flags); auto bp = BufferAllocatedRc::Create(size_t(length), buffer_flags);
// read file content into buffer // read file content into buffer
while (buf_read(fd(), *bp, fn)) while (buf_read(fd(), *bp, fn))

View File

@ -56,7 +56,7 @@ inline void write_atomic(const std::string &fn,
const size_t size_hint, const size_t size_hint,
StrongRandomAPI &rng) StrongRandomAPI &rng)
{ {
BufferPtr bp = new BufferAllocated(size_hint, BufferAllocated::GROW); auto bp = BufferAllocatedRc::Create(size_hint, BufAllocFlags::GROW);
format_compact(root, *bp); format_compact(root, *bp);
write_binary_atomic(fn, tmpdir, mode, mtime_ns, *bp, rng); write_binary_atomic(fn, tmpdir, mode, mtime_ns, *bp, rng);
} }
@ -67,7 +67,7 @@ inline void write_fast(const std::string &fn,
const Json::Value &root, const Json::Value &root,
const size_t size_hint) const size_t size_hint)
{ {
BufferPtr bp = new BufferAllocated(size_hint, BufferAllocated::GROW); auto bp = BufferAllocatedRc::Create(size_hint, BufAllocFlags::GROW);
format_compact(root, *bp); format_compact(root, *bp);
write_binary_unix(fn, mode, mtime_ns, *bp); write_binary_unix(fn, mode, mtime_ns, *bp);
} }

View File

@ -853,7 +853,7 @@ inline void to_uchar(const Json::Value &root,
auto temp = get_int(root, name, title); auto temp = get_int(root, name, title);
dest = clamp_notify<unsigned char>(temp, dest = clamp_notify<unsigned char>(temp,
[](decltype(temp) temp) -> unsigned char [](decltype(temp) temp) -> unsigned char
{ {
auto why = std::string("Conversion error [" + std::to_string(temp) + "] to unsigned char"); auto why = std::string("Conversion error [" + std::to_string(temp) + "] to unsigned char");
throw json_parse(std::move(why)); }); throw json_parse(std::move(why)); });
} }
@ -911,9 +911,9 @@ inline void format_compact(const Json::Value &root, Buffer &buf)
inline std::string format_compact(const Json::Value &root, inline std::string format_compact(const Json::Value &root,
const size_t size_hint = 256) const size_t size_hint = 256)
{ {
BufferPtr bp = new BufferAllocated(size_hint, BufferAllocated::GROW); auto bp = BufferAllocated(size_hint, BufAllocFlags::GROW);
format_compact(root, *bp); format_compact(root, bp);
return buf_to_string(*bp); return buf_to_string(bp);
} }
inline void format(const Json::Value &root, Buffer &buf) inline void format(const Json::Value &root, Buffer &buf)

View File

@ -0,0 +1,91 @@
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2024- OpenVPN Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <openvpn/common/rc.hpp>
namespace openvpn {
/**
* @brief A class template that enables reference counting for a given type.
* @details This class inherits from both the TypeT and RcT (Reference Counting)
* classes. It provides a convenient way to create reference-counted
* objects of TypeT.
* @tparam TypeT The base type to be reference-counted.
* @tparam RcT The reference counting class, defaulting to RC<thread_unsafe_refcount>.
*/
template <typename TypeT, typename RcT = RC<thread_unsafe_refcount>>
class RcEnable : public TypeT, public RcT
{
public:
using Ptr = RCPtr<RcEnable>; ///< Alias for the pointer type used by the reference counting class.
/**
* @brief Creates a new instance of RcEnable with the given arguments.
* @details This function creates a new RcEnable object using the provided arguments
* and returns a smart pointer (Ptr) to the created object.
* @tparam ArgsT The parameter pack types for the arguments to be forwarded
* to the RcEnable constructor.
* @param args The arguments to be forwarded to the RcEnable constructor.
* @return A smart pointer (Ptr) to the newly created RcEnable object with intrusive ref count.
*/
template <typename... ArgsT>
[[nodiscard]] static Ptr Create(ArgsT &&...args)
{
return Ptr(new RcEnable(std::forward<ArgsT>(args)...));
}
private:
/**
* @brief Private constructor for RcEnable.
* @details This constructor is used to create a new instance of RcEnable with the
* provided arguments. It initializes the base classes TypeT and RcT with
* the forwarded arguments.
* @tparam ArgsT The parameter pack types for the arguments to be forwarded
* to the base class constructors.
* @param args The arguments to be forwarded to the base class constructors.
* @note This constructor is private and should not be called directly.
* Use the Create() function to create instances of RcEnable.
*/
template <typename... ArgsT>
RcEnable(ArgsT &&...args)
: TypeT(std::forward<ArgsT>(args)...),
RcT(){};
};
/**
* @brief Helper function to create a reference-counted object with the default thread-unsafe reference counting policy.
* @tparam TypeT The type of the object to be created.
* @tparam RcT The RC type that shall be used, defaults to RC<thread_unsafe_refcount>
* @tparam ArgsT The types of the arguments to be forwarded to the constructor of TypeT.
* @param args The arguments to be forwarded to the constructor of TypeT.
* @return A reference-counted object of type TypeT, using the default thread-unsafe reference counting policy.
* @note This function is a convenience wrapper around make_rc_impl, using the default RC<thread_unsafe_refcount>
* as the reference counting policy.
*/
template <typename TypeT, typename RcT = RC<thread_unsafe_refcount>, typename... ArgsT>
auto make_rc(ArgsT &&...args)
{
return RcEnable<TypeT, RcT>::Create(std::forward<ArgsT>(args)...);
}
} // namespace openvpn

View File

@ -231,7 +231,7 @@ inline BufferPtr string_to_utf16(const STRING &str)
dest + str.length(), dest + str.length(),
lenientConversion); lenientConversion);
conversion_result_throw(res); conversion_result_throw(res);
BufferPtr ret(new BufferAllocated((dest - utf16_dest.get()) * 2, BufferAllocated::ARRAY)); auto ret = BufferAllocatedRc::Create((dest - utf16_dest.get()) * 2, BufAllocFlags::ARRAY);
UTF8 *d = ret->data(); UTF8 *d = ret->data();
for (const UTF16 *s = utf16_dest.get(); s < dest; ++s) for (const UTF16 *s = utf16_dest.get(); s < dest; ++s)
{ {

View File

@ -51,7 +51,7 @@ class CompressLZO : public Compress
asym(asym_arg) asym(asym_arg)
{ {
OVPN_LOG_INFO("LZO init swap=" << support_swap_arg << " asym=" << asym_arg); OVPN_LOG_INFO("LZO init swap=" << support_swap_arg << " asym=" << asym_arg);
lzo_workspace.init(LZO1X_1_15_MEM_COMPRESS, BufferAllocated::ARRAY); lzo_workspace.init(LZO1X_1_15_MEM_COMPRESS, BufAllocFlags::ARRAY);
} }
static void init_static() static void init_static()

View File

@ -22,6 +22,7 @@
#ifndef OPENVPN_COMPRESS_LZOASYM_H #ifndef OPENVPN_COMPRESS_LZOASYM_H
#define OPENVPN_COMPRESS_LZOASYM_H #define OPENVPN_COMPRESS_LZOASYM_H
#include <openvpn/buffer/buffer.hpp>
#include <openvpn/compress/lzoasym_impl.hpp> #include <openvpn/compress/lzoasym_impl.hpp>
// Implement asymmetrical LZO compression (only uncompress, don't compress) // Implement asymmetrical LZO compression (only uncompress, don't compress)

View File

@ -61,7 +61,7 @@ class HashString
BufferPtr final() BufferPtr final()
{ {
BufferPtr ret(new BufferAllocated(ctx->size(), BufferAllocated::ARRAY)); auto ret = BufferAllocatedRc::Create(ctx->size(), BufAllocFlags::ARRAY);
ctx->final(ret->data()); ctx->final(ret->data());
return ret; return ret;
} }

View File

@ -47,7 +47,7 @@ class StaticKey
{ {
} }
StaticKey(const unsigned char *key_data, const size_t key_size) StaticKey(const unsigned char *key_data, const size_t key_size)
: key_data_(key_data, key_size, key_t::DESTRUCT_ZERO) : key_data_(key_data, key_size, BufAllocFlags::DESTRUCT_ZERO)
{ {
} }
@ -71,7 +71,7 @@ class StaticKey
void parse_from_base64(const std::string &b64, const size_t capacity) void parse_from_base64(const std::string &b64, const size_t capacity)
{ {
key_data_.reset(capacity, key_t::DESTRUCT_ZERO); key_data_.reset(capacity, BufAllocFlags::DESTRUCT_ZERO);
base64->decode(key_data_, b64); base64->decode(key_data_, b64);
} }
@ -82,7 +82,7 @@ class StaticKey
void init_from_rng(StrongRandomAPI &rng, const size_t key_size) void init_from_rng(StrongRandomAPI &rng, const size_t key_size)
{ {
key_data_.init(key_size, key_t::DESTRUCT_ZERO); key_data_.init(key_size, BufAllocFlags::DESTRUCT_ZERO);
rng.rand_bytes(key_data_.data(), key_size); rng.rand_bytes(key_data_.data(), key_size);
key_data_.set_size(key_size); key_data_.set_size(key_size);
} }
@ -151,7 +151,7 @@ class OpenVPNStaticKey
void parse(const std::string &key_text) void parse(const std::string &key_text)
{ {
SplitLines in(key_text, 0); SplitLines in(key_text, 0);
key_t data(KEY_SIZE, key_t::DESTRUCT_ZERO); key_t data(KEY_SIZE, BufAllocFlags::DESTRUCT_ZERO);
bool in_body = false; bool in_body = false;
while (in(true)) while (in(true))
{ {
@ -182,7 +182,7 @@ class OpenVPNStaticKey
unsigned char *raw_alloc() unsigned char *raw_alloc()
{ {
key_data_.init(KEY_SIZE, key_t::DESTRUCT_ZERO | key_t::ARRAY); key_data_.init(KEY_SIZE, BufAllocFlags::DESTRUCT_ZERO | BufAllocFlags::ARRAY);
return key_data_.data(); return key_data_.data();
} }

View File

@ -45,7 +45,7 @@ class TLSCryptV2ServerKey
TLSCryptV2ServerKey() TLSCryptV2ServerKey()
: key_size(128), : key_size(128),
key(key_size, BufferAllocated::DESTRUCT_ZERO) key(key_size, BufAllocFlags::DESTRUCT_ZERO)
{ {
} }
@ -111,7 +111,7 @@ class TLSCryptV2ClientKey
void parse(const std::string &key_text) void parse(const std::string &key_text)
{ {
BufferAllocated data(key_size + WKC_MAX_SIZE, BufferAllocated::DESTRUCT_ZERO); BufferAllocated data(key_size + WKC_MAX_SIZE, BufAllocFlags::DESTRUCT_ZERO);
if (!SSLLib::PEMAPI::pem_decode(data, key_text.c_str(), key_text.length(), tls_crypt_v2_client_key_name)) if (!SSLLib::PEMAPI::pem_decode(data, key_text.c_str(), key_text.length(), tls_crypt_v2_client_key_name))
throw tls_crypt_v2_client_key_parse_error(); throw tls_crypt_v2_client_key_parse_error();
@ -119,8 +119,8 @@ class TLSCryptV2ClientKey
if (data.size() < (tag_size + key_size)) if (data.size() < (tag_size + key_size))
throw tls_crypt_v2_client_key_bad_size(); throw tls_crypt_v2_client_key_bad_size();
key.init(data.data(), key_size, BufferAllocated::DESTRUCT_ZERO); key.init(data.data(), key_size, BufAllocFlags::DESTRUCT_ZERO);
wkc.init(data.data() + key_size, data.size() - key_size, BufferAllocated::DESTRUCT_ZERO); wkc.init(data.data() + key_size, data.size() - key_size, BufAllocFlags::DESTRUCT_ZERO);
} }
void extract_key(OpenVPNStaticKey &tls_key) void extract_key(OpenVPNStaticKey &tls_key)
@ -131,7 +131,7 @@ class TLSCryptV2ClientKey
std::string render() const std::string render() const
{ {
BufferAllocated data(32 + 2 * (key.size() + wkc.size()), 0); BufferAllocated data(32 + 2 * (key.size() + wkc.size()), 0);
BufferAllocated in(key, BufferAllocated::GROW); BufferAllocated in(key, BufAllocFlags::GROW);
in.append(wkc); in.append(wkc);
if (!SSLLib::PEMAPI::pem_encode(data, in.c_data(), in.size(), tls_crypt_v2_client_key_name)) if (!SSLLib::PEMAPI::pem_encode(data, in.c_data(), in.size(), tls_crypt_v2_client_key_name))

View File

@ -643,7 +643,7 @@ class OvpnDcoClient : public Client,
// good enough values for control channel packets // good enough values for control channel packets
pkt->buf.reset(512, pkt->buf.reset(512,
3072, 3072,
BufferAllocated::GROW | BufferAllocated::CONSTRUCT_ZERO | BufferAllocated::DESTRUCT_ZERO); BufAllocFlags::GROW | BufAllocFlags::CONSTRUCT_ZERO | BufAllocFlags::DESTRUCT_ZERO);
pipe->async_read_some( pipe->async_read_some(
pkt->buf.mutable_buffer(), pkt->buf.mutable_buffer(),
[self = Ptr(this), [self = Ptr(this),

View File

@ -84,7 +84,7 @@ class Frame : public RC<thread_unsafe_refcount>
const size_t tailroom, const size_t tailroom,
const size_t align_adjust, // length of leading prefix data before the data that needs to be aligned on a size_t boundary const size_t align_adjust, // length of leading prefix data before the data that needs to be aligned on a size_t boundary
const size_t align_block, // size of alignment block, usually sizeof(size_t) but sometimes the cipher block size const size_t align_block, // size of alignment block, usually sizeof(size_t) but sometimes the cipher block size
const unsigned int buffer_flags) // flags passed to BufferAllocated constructor const unsigned int buffer_flags) // flags passed to BufferAllocatedRc constructor
{ {
headroom_ = headroom; headroom_ = headroom;
payload_ = payload; payload_ = payload;
@ -144,11 +144,11 @@ class Frame : public RC<thread_unsafe_refcount>
buf.realign(actual_headroom(buf.c_data_raw())); buf.realign(actual_headroom(buf.c_data_raw()));
} }
// Return a new BufferAllocated object initialized with the given data. // Return a new BufferAllocatedRc object initialized with the given data.
BufferPtr copy(const unsigned char *data, const size_t size) const BufferPtr copy(const unsigned char *data, const size_t size) const
{ {
const size_t cap = size + headroom() + tailroom(); const size_t cap = size + headroom() + tailroom();
BufferPtr b = new BufferAllocated(cap, buffer_flags()); auto b = BufferAllocatedRc::Create(cap, buffer_flags());
b->init_headroom(actual_headroom(b->c_data_raw())); b->init_headroom(actual_headroom(b->c_data_raw()));
b->write(data, size); b->write(data, size);
return b; return b;
@ -164,13 +164,13 @@ class Frame : public RC<thread_unsafe_refcount>
return b; return b;
} }
// Return a new BufferAllocated object initialized with // Return a new BufferAllocatedRc object initialized with
// the data in given buffer. buf may be empty or undefined. // the data in given buffer. buf may be empty or undefined.
BufferPtr copy(const BufferPtr &buf) const BufferPtr copy(const BufferPtr &buf) const
{ {
const size_t size = buf ? buf->size() : 0; const size_t size = buf ? buf->size() : 0;
const size_t cap = size + headroom() + tailroom(); const size_t cap = size + headroom() + tailroom();
BufferPtr b = new BufferAllocated(cap, buffer_flags()); auto b = BufferAllocatedRc::Create(cap, buffer_flags());
b->init_headroom(actual_headroom(b->c_data_raw())); b->init_headroom(actual_headroom(b->c_data_raw()));
if (size) if (size)
b->write(buf->c_data(), size); b->write(buf->c_data(), size);
@ -280,7 +280,7 @@ class Frame : public RC<thread_unsafe_refcount>
BufferPtr prepare(const unsigned int context) const BufferPtr prepare(const unsigned int context) const
{ {
BufferPtr buf(new BufferAllocated()); auto buf = BufferAllocatedRc::Create();
prepare(context, *buf); prepare(context, *buf);
return buf; return buf;
} }

View File

@ -58,7 +58,7 @@ inline Frame::Ptr frame_init(const bool align_adjust_3_1,
tailroom, tailroom,
0, 0,
align_block, align_block,
BufferAllocated::GROW); BufAllocFlags::GROW);
frame->standardize_capacity(~0); frame->standardize_capacity(~0);
if (verbose) if (verbose)

View File

@ -77,7 +77,7 @@ class MemQStream : public MemQBase
// Start a new buffer // Start a new buffer
while (b.size()) while (b.size())
{ {
BufferPtr newbuf(new BufferAllocated); auto newbuf = BufferAllocatedRc::Create();
fc.prepare(*newbuf); fc.prepare(*newbuf);
const size_t write_size = std::min(b.size(), fc.payload()); const size_t write_size = std::min(b.size(), fc.payload());
const unsigned char *from = b.read_alloc(write_size); const unsigned char *from = b.read_alloc(write_size);

View File

@ -80,7 +80,7 @@ class MbedTLSPEM
{ {
size_t buflen = 0; size_t buflen = 0;
const uint8_t *bufptr = mbedtls_pem_get_buffer(&ctx, &buflen); const uint8_t *bufptr = mbedtls_pem_get_buffer(&ctx, &buflen);
dst.init(bufptr, buflen, BufferAllocated::DESTRUCT_ZERO); dst.init(bufptr, buflen, BufAllocFlags::DESTRUCT_ZERO);
} }
mbedtls_pem_free(&ctx); mbedtls_pem_free(&ctx);

View File

@ -930,7 +930,7 @@ class OMICore : public Acceptor::ListenerBase
{ {
if (!is_sock_open() || recv_queued) if (!is_sock_open() || recv_queued)
return; return;
BufferPtr buf(new BufferAllocated(256, 0)); BufferPtr buf = BufferAllocatedRc::Create(256, 0);
socket->async_receive(buf->mutable_buffer_clamp(), socket->async_receive(buf->mutable_buffer_clamp(),
[self = Ptr(this), sock = socket, buf](const openvpn_io::error_code &error, const size_t bytes_recvd) [self = Ptr(this), sock = socket, buf](const openvpn_io::error_code &error, const size_t bytes_recvd)
{ {
@ -990,7 +990,7 @@ class OMICore : public Acceptor::ListenerBase
{ {
if (!is_sock_open()) if (!is_sock_open())
return; return;
BufferAllocated &buf = *content_out.front(); auto &buf = *content_out.front();
socket->async_send(buf.const_buffer_clamp(), socket->async_send(buf.const_buffer_clamp(),
[self = Ptr(this), sock = socket](const openvpn_io::error_code &error, const size_t bytes_sent) [self = Ptr(this), sock = socket](const openvpn_io::error_code &error, const size_t bytes_sent)
{ {

View File

@ -97,7 +97,7 @@ class PushContinuationFragment : public std::vector<BufferPtr>
total_size += e->size(); total_size += e->size();
// allocate return buffer // allocate return buffer
BufferPtr ret(new BufferAllocated(total_size, 0)); auto ret = BufferAllocatedRc::Create(total_size, 0);
buf_append_string(*ret, "PUSH_REPLY"); buf_append_string(*ret, "PUSH_REPLY");
// terminators // terminators
@ -163,7 +163,7 @@ class PushContinuationFragment : public std::vector<BufferPtr>
void append_new_buffer() void append_new_buffer()
{ {
// include extra byte for null termination // include extra byte for null termination
BufferPtr bp = new BufferAllocated(FRAGMENT_SIZE + 1, 0); auto bp = BufferAllocatedRc::Create(FRAGMENT_SIZE + 1, 0);
buf_append_string(*bp, "PUSH_REPLY"); buf_append_string(*bp, "PUSH_REPLY");
push_back(std::move(bp)); push_back(std::move(bp));
} }

View File

@ -459,7 +459,7 @@ class MyClientInstance : public WS::Server::Listener::Client
void http_content_in(BufferAllocated &buf) override void http_content_in(BufferAllocated &buf) override
{ {
if (buf.defined()) if (buf.defined())
in.emplace_back(new BufferAllocated(std::move(buf))); in.emplace_back(BufferAllocatedRc::Create(std::move(buf)));
} }
BufferPtr http_content_out() override BufferPtr http_content_out() override

View File

@ -812,7 +812,7 @@ class MyClientInstance : public WS::Server::Listener::Client
void http_content_in(BufferAllocated &buf) override void http_content_in(BufferAllocated &buf) override
{ {
if (buf.defined()) if (buf.defined())
in.emplace_back(new BufferAllocated(std::move(buf))); in.emplace_back(BufferAllocatedRc::Create(std::move(buf)));
} }
BufferPtr http_content_out() override BufferPtr http_content_out() override

View File

@ -152,7 +152,7 @@ class NTLM
std::memcpy(ntlmv2_response, ntlmv2_hmacmd5, 16); std::memcpy(ntlmv2_response, ntlmv2_hmacmd5, 16);
// start building phase3 message (what we return to caller) // start building phase3 message (what we return to caller)
BufferAllocated phase3(0x40, BufferAllocated::ARRAY | BufferAllocated::CONSTRUCT_ZERO | BufferAllocated::GROW); BufferAllocated phase3(0x40, BufAllocFlags::ARRAY | BufAllocFlags::CONSTRUCT_ZERO | BufAllocFlags::GROW);
std::strcpy((char *)phase3.data(), "NTLMSSP"); // signature std::strcpy((char *)phase3.data(), "NTLMSSP"); // signature
phase3[8] = 3; // type 3 phase3[8] = 3; // type 3

View File

@ -408,7 +408,7 @@ class ServerProto
if (proto_context.primary_defined()) if (proto_context.primary_defined())
{ {
BufferPtr buf(new BufferAllocated(64, 0)); auto buf = BufferAllocatedRc::Create(64, 0);
buf_append_string(*buf, "RELAY"); buf_append_string(*buf, "RELAY");
buf->null_terminate(); buf->null_terminate();
proto_context.control_send(std::move(buf)); proto_context.control_send(std::move(buf));
@ -465,7 +465,7 @@ class ServerProto
proto_context.update_now(); proto_context.update_now();
BufferPtr buf(new BufferAllocated(128, BufferAllocated::GROW)); auto buf = BufferAllocatedRc::Create(128, BufAllocFlags::GROW);
BufferStreamOut os(*buf); BufferStreamOut os(*buf);
std::string ts; std::string ts;

View File

@ -183,7 +183,7 @@ class AppControlMessageReceiver
bool receive_message(const std::string &msg) bool receive_message(const std::string &msg)
{ {
if (!recvbuf.defined()) if (!recvbuf.defined())
recvbuf.reset(256, BufferAllocated::GROW); recvbuf.reset(256, BufAllocFlags::GROW);
// msg includes ACC, prefix // msg includes ACC, prefix
auto parts = string::split(msg, ',', 4); auto parts = string::split(msg, ',', 4);
if (parts.size() != 5 || parts[0] != "ACC") if (parts.size() != 5 || parts[0] != "ACC")

View File

@ -1595,7 +1595,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
void write_control_string(const S &str) void write_control_string(const S &str)
{ {
const size_t len = str.length(); const size_t len = str.length();
BufferPtr bp = new BufferAllocated(len + 1, 0); auto bp = BufferAllocatedRc::Create(len + 1, 0);
write_control_string(str, *bp); write_control_string(str, *bp);
control_send(std::move(bp)); control_send(std::move(bp));
} }
@ -1623,7 +1623,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
{ {
Packet pkt; Packet pkt;
pkt.opcode = opcode; pkt.opcode = opcode;
pkt.buf.reset(new BufferAllocated(*buf)); pkt.buf = BufferAllocatedRc::Create(*buf);
return pkt; return pkt;
} }
@ -1636,7 +1636,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
void frame_prepare(const Frame &frame, const unsigned int context) void frame_prepare(const Frame &frame, const unsigned int context)
{ {
if (!buf) if (!buf)
buf.reset(new BufferAllocated()); buf = BufferAllocatedRc::Create();
frame.prepare(context, *buf); frame.prepare(context, *buf);
} }
@ -2864,7 +2864,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
void send_auth() void send_auth()
{ {
BufferPtr buf = new BufferAllocated(); auto buf = BufferAllocatedRc::Create();
proto.config->frame->prepare(Frame::WRITE_SSL_CLEARTEXT, *buf); proto.config->frame->prepare(Frame::WRITE_SSL_CLEARTEXT, *buf);
buf->write(proto_context_private::auth_prefix, sizeof(proto_context_private::auth_prefix)); buf->write(proto_context_private::auth_prefix, sizeof(proto_context_private::auth_prefix));
tlsprf->self_randomize(*proto.config->rng); tlsprf->self_randomize(*proto.config->rng);
@ -2874,7 +2874,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
if (!proto.is_server()) if (!proto.is_server())
{ {
OVPN_LOG_INFO("Tunnel Options:" << options); OVPN_LOG_INFO("Tunnel Options:" << options);
buf->or_flags(BufferAllocated::DESTRUCT_ZERO); buf->or_flags(BufAllocFlags::DESTRUCT_ZERO);
if (proto.config->xmit_creds) if (proto.config->xmit_creds)
proto.client_auth(*buf); proto.client_auth(*buf);
else else
@ -3223,7 +3223,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
bool decapsulate_tls_crypt(Packet &pkt) bool decapsulate_tls_crypt(Packet &pkt)
{ {
BufferAllocated &recv = *pkt.buf; auto &recv = *pkt.buf;
const unsigned char *orig_data = recv.data(); const unsigned char *orig_data = recv.data();
const size_t orig_size = recv.size(); const size_t orig_size = recv.size();
@ -3357,7 +3357,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
if ((wkc_len - sizeof(uint16_t)) != wkc_raw_size) if ((wkc_len - sizeof(uint16_t)) != wkc_raw_size)
return false; return false;
BufferAllocated plaintext(wkc_len, BufferAllocated::CONSTRUCT_ZERO); BufferAllocated plaintext(wkc_len, BufAllocFlags::CONSTRUCT_ZERO);
// plaintext will be used to compute the Auth Tag, therefore start by prepending // plaintext will be used to compute the Auth Tag, therefore start by prepending
// the WKc length in network order // the WKc length in network order
wkc_len = htons(wkc_len); wkc_len = htons(wkc_len);
@ -4096,7 +4096,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
void control_send(BufferAllocated &&app_buf) void control_send(BufferAllocated &&app_buf)
{ {
control_send(app_buf.move_to_ptr()); control_send(BufferAllocatedRc::Create(std::move(app_buf)));
} }
// validate a control channel network packet // validate a control channel network packet
@ -4109,14 +4109,14 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
bool control_net_recv(const PacketType &type, BufferAllocated &&net_buf) bool control_net_recv(const PacketType &type, BufferAllocated &&net_buf)
{ {
Packet pkt(net_buf.move_to_ptr(), type.opcode); Packet pkt(BufferAllocatedRc::Create(std::move(net_buf)), type.opcode);
if (type.is_soft_reset() && !renegotiate_request(pkt)) if (type.is_soft_reset() && !renegotiate_request(pkt))
return false; return false;
return select_key_context(type, true).net_recv(std::move(pkt)); return select_key_context(type, true).net_recv(std::move(pkt));
} }
// this version only appears to support test_proto.cpp; suggest creating a // this version only appears to support test_proto.cpp; suggest creating a
// local BufferAllocated and move the BufferPtr contents into it; then use // local BufferAllocatedRc and move the BufferPtr contents into it; then use
// the version above // the version above
bool control_net_recv(const PacketType &type, BufferPtr &&net_bp) bool control_net_recv(const PacketType &type, BufferPtr &&net_bp)
{ {

View File

@ -451,7 +451,7 @@ class ProtoStackBase
while (ssl_->read_cleartext_ready()) while (ssl_->read_cleartext_ready())
{ {
ssize_t size; ssize_t size;
to_app_buf.reset(new BufferAllocated()); to_app_buf = BufferAllocatedRc::Create();
frame_->prepare(Frame::READ_SSL_CLEARTEXT, *to_app_buf); frame_->prepare(Frame::READ_SSL_CLEARTEXT, *to_app_buf);
try try
{ {

View File

@ -156,7 +156,7 @@ class TLSPRF
+ client_seed_len + client_seed_len
+ server_seed_len + server_seed_len
+ ProtoSessionID::SIZE * 2, + ProtoSessionID::SIZE * 2,
BufferAllocated::DESTRUCT_ZERO); BufAllocFlags::DESTRUCT_ZERO);
seed.write((unsigned char *)label, label_len); seed.write((unsigned char *)label, label_len);
seed.write(client_seed, client_seed_len); seed.write(client_seed, client_seed_len);
seed.write(server_seed, server_seed_len); seed.write(server_seed, server_seed_len);

View File

@ -203,9 +203,9 @@ class PacketStream
static void validate_size(const size_t size, const Frame::Context &frame_context) static void validate_size(const size_t size, const Frame::Context &frame_context)
{ {
// Don't validate upper bound on size if BufferAllocated::GROW is set, // Don't validate upper bound on size if BufAllocFlags::GROW is set,
// allowing it to range up to larger sizes. // allowing it to range up to larger sizes.
if (!size || (!(frame_context.buffer_flags() & BufferAllocated::GROW) && size > frame_context.payload())) if (!size || (!(frame_context.buffer_flags() & BufAllocFlags::GROW) && size > frame_context.payload()))
throw embedded_packet_size_error(); throw embedded_packet_size_error();
} }

View File

@ -153,7 +153,7 @@ class LinkCommon : public LinkBase
} }
else else
{ {
buf.reset(new BufferAllocated()); buf = BufferAllocatedRc::Create();
} }
buf->swap(b); buf->swap(b);
if (!is_raw_mode_write()) if (!is_raw_mode_write())

View File

@ -219,7 +219,7 @@ class UDPLink : public RC<thread_unsafe_refcount>
std::unique_ptr<AsioEndpoint> ep; std::unique_ptr<AsioEndpoint> ep;
if (endpoint) if (endpoint)
ep.reset(new AsioEndpoint(*endpoint)); ep.reset(new AsioEndpoint(*endpoint));
gremlin->send_queue([self = Ptr(this), buf = BufferAllocated(buf, 0), ep = std::move(ep)]() mutable gremlin->send_queue([self = Ptr(this), buf = BufferAllocatedRc(buf, 0), ep = std::move(ep)]() mutable
{ {
if (!self->halt) if (!self->halt)
self->do_send(buf, ep.get()); }); self->do_send(buf, ep.get()); });

View File

@ -755,7 +755,7 @@ class GeNL : public RC<thread_unsafe_refcount>
void reset_buffer() void reset_buffer()
{ {
// good enough values to handle control packets // good enough values to handle control packets
buf.reset(512, 3072, BufferAllocated::GROW | BufferAllocated::CONSTRUCT_ZERO | BufferAllocated::DESTRUCT_ZERO); buf.reset(512, 3072, BufAllocFlags::GROW | BufAllocFlags::CONSTRUCT_ZERO | BufAllocFlags::DESTRUCT_ZERO);
} }
/** /**

View File

@ -59,7 +59,7 @@ enum
inline IP::Addr cvt_pnr_ip_v4(const std::string &hexaddr) inline IP::Addr cvt_pnr_ip_v4(const std::string &hexaddr)
{ {
BufferAllocated v(4, BufferAllocated::CONSTRUCT_ZERO); BufferAllocated v(4, BufAllocFlags::CONSTRUCT_ZERO);
parse_hex(v, hexaddr); parse_hex(v, hexaddr);
if (v.size() != 4) if (v.size() != 4)
throw tun_linux_error("bad hex address"); throw tun_linux_error("bad hex address");

View File

@ -512,7 +512,7 @@ inline int iface_del(std::ostringstream &os, const std::string &dev)
/*inline IPv4::Addr cvt_pnr_ip_v4(const std::string& hexaddr) /*inline IPv4::Addr cvt_pnr_ip_v4(const std::string& hexaddr)
{ {
BufferAllocated v(4, BufferAllocated::CONSTRUCT_ZERO); BufferAllocated v(4, BufAllocFlags::CONSTRUCT_ZERO);
parse_hex(v, hexaddr); parse_hex(v, hexaddr);
if (v.size() != 4) if (v.size() != 4)
throw tun_linux_error("bad hex address"); throw tun_linux_error("bad hex address");

View File

@ -475,7 +475,7 @@ struct DeviceInstanceIdInterfaceList : public std::vector<DeviceInstanceIdInterf
LONG status = RegQueryValueExA(regkey(), "NetCfgInstanceId", NULL, NULL, NULL, &size); LONG status = RegQueryValueExA(regkey(), "NetCfgInstanceId", NULL, NULL, NULL, &size);
if (status != ERROR_SUCCESS) if (status != ERROR_SUCCESS)
continue; continue;
BufferAllocatedType<char, thread_unsafe_refcount> buf_net_cfg_inst_id(size, BufferAllocated::CONSTRUCT_ZERO); BufferAllocatedType<char> buf_net_cfg_inst_id(size, BufAllocFlags::CONSTRUCT_ZERO);
status = RegQueryValueExA(regkey(), "NetCfgInstanceId", NULL, NULL, (LPBYTE)buf_net_cfg_inst_id.data(), &size); status = RegQueryValueExA(regkey(), "NetCfgInstanceId", NULL, NULL, (LPBYTE)buf_net_cfg_inst_id.data(), &size);
if (status == ERROR_SUCCESS) if (status == ERROR_SUCCESS)
@ -490,7 +490,7 @@ struct DeviceInstanceIdInterfaceList : public std::vector<DeviceInstanceIdInterf
if (res != FALSE && GetLastError() != ERROR_INSUFFICIENT_BUFFER) if (res != FALSE && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
continue; continue;
BufferAllocatedType<char, thread_unsafe_refcount> buf_dev_inst_id(size, BufferAllocated::CONSTRUCT_ZERO); BufferAllocatedType<char> buf_dev_inst_id(size, BufAllocFlags::CONSTRUCT_ZERO);
if (!SetupDiGetDeviceInstanceId(device_info_set, &dev_info_data, buf_dev_inst_id.data(), size, &size)) if (!SetupDiGetDeviceInstanceId(device_info_set, &dev_info_data, buf_dev_inst_id.data(), size, &size))
continue; continue;
buf_dev_inst_id.set_size(size); buf_dev_inst_id.set_size(size);
@ -504,7 +504,7 @@ struct DeviceInstanceIdInterfaceList : public std::vector<DeviceInstanceIdInterf
if (cr != CR_SUCCESS) if (cr != CR_SUCCESS)
continue; continue;
BufferAllocatedType<char, thread_unsafe_refcount> buf_dev_iface_list(dev_interface_list_size, BufferAllocated::CONSTRUCT_ZERO); BufferAllocatedType<char> buf_dev_iface_list(dev_interface_list_size, BufAllocFlags::CONSTRUCT_ZERO);
cr = CM_Get_Device_Interface_List((LPGUID)&GUID_DEVINTERFACE_NET, cr = CM_Get_Device_Interface_List((LPGUID)&GUID_DEVINTERFACE_NET,
buf_dev_inst_id.data(), buf_dev_inst_id.data(),
buf_dev_iface_list.data(), buf_dev_iface_list.data(),

View File

@ -1095,7 +1095,7 @@ class HTTPCore : public Base, public TransportClientParent
const Request req = http_request(); const Request req = http_request();
content_info = http_content_info(); content_info = http_content_info();
outbuf.reset(new BufferAllocated(512, BufferAllocated::GROW)); outbuf = BufferAllocatedRc::Create(512, BufAllocFlags::GROW);
BufferStreamOut os(*outbuf); BufferStreamOut os(*outbuf);
if (content_info.websocket) if (content_info.websocket)

View File

@ -835,7 +835,7 @@ class ClientSet : public RC<thread_unsafe_refcount>
{ {
if (out_iter != trans().content_out.end()) if (out_iter != trans().content_out.end())
{ {
BufferPtr ret = new BufferAllocated(**out_iter); auto ret = BufferAllocatedRc::Create(**out_iter);
++out_iter; ++out_iter;
return ret; return ret;
} }

View File

@ -230,7 +230,7 @@ class HTTPBase : public REFCOUNT_BASE
if (ssl_sess) if (ssl_sess)
{ {
// HTTPS // HTTPS
BufferPtr buf(new BufferAllocated()); auto buf = BufferAllocatedRc::Create();
buf->swap(b); // take ownership buf->swap(b); // take ownership
ssl_sess->write_ciphertext(buf); ssl_sess->write_ciphertext(buf);
ssl_up_stack(); ssl_up_stack();
@ -252,10 +252,10 @@ class HTTPBase : public REFCOUNT_BASE
// void base_http_content_out_needed(); // void base_http_content_out_needed();
// void base_http_out_eof(); // void base_http_out_eof();
// bool base_http_headers_received(); // bool base_http_headers_received();
// void base_http_content_in(BufferAllocated& buf); // void base_http_content_in(BufferAllocatedRc& buf);
// bool base_link_send(BufferAllocated& buf); // bool base_link_send(BufferAllocatedRc& buf);
// bool base_send_queue_empty(); // bool base_send_queue_empty();
// void base_http_done_handler(BufferAllocated& residual) // void base_http_done_handler(BufferAllocatedRc& residual)
// void base_error_handler(const int errcode, const std::string& err); // void base_error_handler(const int errcode, const std::string& err);
// protected member vars // protected member vars

View File

@ -306,7 +306,7 @@ class Listener : public ProxyListener
content_info = std::move(ci); content_info = std::move(ci);
outbuf.reset(new BufferAllocated(512, BufferAllocated::GROW)); outbuf = BufferAllocatedRc::Create(512, BufAllocFlags::GROW);
BufferStreamOut os(*outbuf); BufferStreamOut os(*outbuf);
// websocket? // websocket?

View File

@ -333,7 +333,7 @@ class Receiver
if (!buf.allocated()) if (!buf.allocated())
{ {
buf = std::move(inbuf); buf = std::move(inbuf);
buf.or_flags(BufferAllocated::GROW); buf.or_flags(BufAllocFlags::GROW);
} }
else else
buf.append(inbuf); buf.append(inbuf);

View File

@ -533,7 +533,7 @@ class Client : public ClientBase
{ {
using PKEY_CTX_unique_ptr = std::unique_ptr<::EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>; using PKEY_CTX_unique_ptr = std::unique_ptr<::EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>;
BufferAllocated signdata(256, BufferAllocated::GROW); BufferAllocated signdata(256, BufAllocFlags::GROW);
base64->decode(signdata, signreq.data); base64->decode(signdata, signreq.data);
EVP_PKEY *pkey = epki_pkey.obj(); EVP_PKEY *pkey = epki_pkey.obj();
@ -572,7 +572,7 @@ class Client : public ClientBase
throw Exception("epki_sign failed, error signing data: " + openssl_error()); throw Exception("epki_sign failed, error signing data: " + openssl_error());
} }
BufferAllocated sig(outlen, BufferAllocated::ARRAY); BufferAllocated sig(outlen, BufAllocFlags::ARRAY);
if ((EVP_PKEY_sign(pkey_ctx.get(), sig.data(), &outlen, signdata.c_data(), signdata.size())) < 0) if ((EVP_PKEY_sign(pkey_ctx.get(), sig.data(), &outlen, signdata.c_data(), signdata.size())) < 0)
{ {
@ -598,7 +598,7 @@ class Client : public ClientBase
void doOpenSSLDigestSignature(ClientAPI::ExternalPKISignRequest &signreq) void doOpenSSLDigestSignature(ClientAPI::ExternalPKISignRequest &signreq)
{ {
EVP_PKEY_CTX *pkey_ctx = nullptr; EVP_PKEY_CTX *pkey_ctx = nullptr;
BufferAllocated signdata(256, BufferAllocated::GROW); BufferAllocated signdata(256, BufAllocFlags::GROW);
base64->decode(signdata, signreq.data); base64->decode(signdata, signreq.data);
using MD_unique_ptr = std::unique_ptr<::EVP_MD_CTX, decltype(&::EVP_MD_CTX_free)>; using MD_unique_ptr = std::unique_ptr<::EVP_MD_CTX, decltype(&::EVP_MD_CTX_free)>;
@ -660,7 +660,7 @@ class Client : public ClientBase
throw Exception("epki_sign failed, error signing data: " + openssl_error()); throw Exception("epki_sign failed, error signing data: " + openssl_error());
} }
BufferAllocated sig(outlen, BufferAllocated::ARRAY); BufferAllocated sig(outlen, BufAllocFlags::ARRAY);
if (EVP_DigestSign(md.get(), sig.data(), &outlen, signdata.data(), signdata.size()) < 0) if (EVP_DigestSign(md.get(), sig.data(), &outlen, signdata.data(), signdata.size()) < 0)
{ {
@ -694,7 +694,7 @@ class Client : public ClientBase
try try
{ {
// decode base64 sign request // decode base64 sign request
BufferAllocated signdata(256, BufferAllocated::GROW); BufferAllocated signdata(256, BufAllocFlags::GROW);
base64->decode(signdata, signreq.data); base64->decode(signdata, signreq.data);
// get MD alg // get MD alg
@ -704,7 +704,7 @@ class Client : public ClientBase
OPENVPN_LOG("SIGN[" << PKCS1::DigestPrefix::MbedTLSParse::to_string(md_alg) << ',' << signdata.size() << "]: " << render_hex_generic(signdata)); OPENVPN_LOG("SIGN[" << PKCS1::DigestPrefix::MbedTLSParse::to_string(md_alg) << ',' << signdata.size() << "]: " << render_hex_generic(signdata));
// allocate buffer for signature // allocate buffer for signature
BufferAllocated sig(mbedtls_pk_get_len(epki_ctx.get()), BufferAllocated::ARRAY); BufferAllocated sig(mbedtls_pk_get_len(epki_ctx.get()), BufAllocFlags::ARRAY);
// sign it // sign it
size_t sig_size = 0; size_t sig_size = 0;

View File

@ -74,6 +74,7 @@ add_executable(coreUnitTests
test_statickey.cpp test_statickey.cpp
test_streq.cpp test_streq.cpp
test_time.cpp test_time.cpp
test_make_rc.cpp
test_typeindex.cpp test_typeindex.cpp
test_tun_builder.cpp test_tun_builder.cpp
test_userpass.cpp test_userpass.cpp

View File

@ -14,7 +14,7 @@ TEST(buffer, const_buffer_ref_1)
EXPECT_EQ(buf_to_string(buf), buf_to_string(cbuf)); EXPECT_EQ(buf_to_string(buf), buf_to_string(cbuf));
} }
// test equality of BufferAllocated and ConstBuffer // test equality of BufferAllocatedRc and ConstBuffer
TEST(buffer, const_buffer_ref_2) TEST(buffer, const_buffer_ref_2)
{ {
BufferAllocated buf(64, 0); BufferAllocated buf(64, 0);
@ -165,7 +165,7 @@ TEST(buffer, alloc_buffer_access1)
// Test read/write access and bounds check // Test read/write access and bounds check
TEST(buffer, alloc_buffer_access2) TEST(buffer, alloc_buffer_access2)
{ {
BufferAllocated buf(64, BufferAllocated::CONSTRUCT_ZERO | BufferAllocated::DESTRUCT_ZERO); BufferAllocated buf(64, BufAllocFlags::CONSTRUCT_ZERO | BufAllocFlags::DESTRUCT_ZERO);
buf_append_string(buf, "hello world"); buf_append_string(buf, "hello world");
buf[0] = 'j'; buf[0] = 'j';

View File

@ -129,7 +129,7 @@ static OptionList random_optionlist(RandomAPI &prng)
static void test_roundtrip(const OptionList &opt_orig) static void test_roundtrip(const OptionList &opt_orig)
{ {
// first render to CSV // first render to CSV
BufferAllocated buf(opt_orig.size() * 128, BufferAllocated::GROW); BufferAllocated buf(opt_orig.size() * 128, BufAllocFlags::GROW);
buf_append_string(buf, "PUSH_REPLY,"); buf_append_string(buf, "PUSH_REPLY,");
buf_append_string(buf, opt_orig.render_csv()); buf_append_string(buf, opt_orig.render_csv());
@ -186,7 +186,7 @@ TEST(continuation, test1)
// push-list for further testing // push-list for further testing
TEST(continuation, test2) TEST(continuation, test2)
{ {
BufferAllocated buf(65536, BufferAllocated::GROW); BufferAllocated buf(65536, BufAllocFlags::GROW);
buf_append_string(buf, "PUSH_REPLY,route-gateway 10.213.0.1,ifconfig 10.213.0.48 255.255.0.0,ifconfig-ipv6 fdab::48/64 fdab::1,client-ip 192.168.4.1,ping 1,ping-restart 8,reneg-sec 60,cipher AES-128-GCM,compress stub-v2,peer-id 4,topology subnet,explicit-exit-notify"); buf_append_string(buf, "PUSH_REPLY,route-gateway 10.213.0.1,ifconfig 10.213.0.48 255.255.0.0,ifconfig-ipv6 fdab::48/64 fdab::1,client-ip 192.168.4.1,ping 1,ping-restart 8,reneg-sec 60,cipher AES-128-GCM,compress stub-v2,peer-id 4,topology subnet,explicit-exit-notify");
// pack the buffers, so several reach the maximum // pack the buffers, so several reach the maximum

View File

@ -0,0 +1,87 @@
#include "test_common.h"
#include <openvpn/common/make_rc.hpp>
using namespace openvpn;
// Tests the RcEnable and make_rc functionality.
struct test1
{
int i = 0;
};
using rc_test1 = RcEnable<test1>;
// The `f_ptr` function checks that the reference-counted object has the expected value.
void f_ptr(rc_test1::Ptr rct1, int i)
{
EXPECT_EQ(rct1->i, i);
}
// Ref to base
void f_ref(test1 &t1, int i)
{
EXPECT_EQ(t1.i, i);
}
// Sliced value
void f_val(test1 t1, int i)
{
EXPECT_EQ(t1.i, i);
}
// The `direct_enable` test verifies that an RcEnable object can be created directly.
TEST(make_rc, direct_enable)
{
auto rct1 = RcEnable<test1>::Create();
EXPECT_EQ(rct1->i, 0);
}
// The `simple` test verifies that a reference-counted object can be created using `make_rc`.
TEST(make_rc, simple)
{
auto rct1 = make_rc<test1>();
EXPECT_EQ(rct1->i, 0);
}
// The `move_init` test verifies that a reference-counted object can be created by moving an existing object.
TEST(make_rc, move_init)
{
auto t = test1();
EXPECT_EQ(t.i, 0);
t.i = 42;
auto rct1 = make_rc<test1>(std::move(t));
EXPECT_EQ(rct1->i, 42);
}
// The `move_init_call` test verifies that a reference-counted object can be created by moving an existing object
// and passed to a function.
TEST(make_rc, move_init_call)
{
auto t = test1();
EXPECT_EQ(t.i, 0);
t.i = 42;
f_ptr(make_rc<test1>(std::move(t)), 42);
}
// Calls using ref
TEST(make_rc, call_value)
{
auto rct1 = RcEnable<test1>::Create();
f_ref(*rct1, 0);
}
// Calls using sliced value
TEST(make_rc, call_slice)
{
auto rct1 = RcEnable<test1>::Create();
f_val(*rct1, 0);
}
// make_rc TS
TEST(make_rc, simple_ts)
{
auto rct1 = make_rc<test1, RC<thread_safe_refcount>>();
EXPECT_EQ(rct1->i, 0);
}

View File

@ -44,8 +44,8 @@ static void do_test(const bool grow, const bool verbose)
const int n_iter = 250000; const int n_iter = 250000;
#endif #endif
const Frame::Context fc(256, 512, 256, 0, sizeof(size_t), grow ? BufferAllocated::GROW : 0); const Frame::Context fc(256, 512, 256, 0, sizeof(size_t), grow ? BufAllocFlags::GROW : 0);
const Frame::Context fc_big(256, 4096, 256, 0, sizeof(size_t), grow ? BufferAllocated::GROW : 0); const Frame::Context fc_big(256, 4096, 256, 0, sizeof(size_t), grow ? BufAllocFlags::GROW : 0);
if (verbose) if (verbose)
{ {
@ -172,7 +172,7 @@ static void validate_size_test()
const size_t tailroom = 0; const size_t tailroom = 0;
const size_t align_block = 16; const size_t align_block = 16;
const Frame::Context fixed(headroom, payload, tailroom, 0, align_block, 0); const Frame::Context fixed(headroom, payload, tailroom, 0, align_block, 0);
const Frame::Context grow(headroom, payload, tailroom, 0, align_block, BufferAllocated::GROW); const Frame::Context grow(headroom, payload, tailroom, 0, align_block, BufAllocFlags::GROW);
validate_size<PKTSTREAM>(fixed, 2048, false); // succeeds validate_size<PKTSTREAM>(fixed, 2048, false); // succeeds
validate_size<PKTSTREAM>(fixed, 2049, true); // exceeded payload, throw validate_size<PKTSTREAM>(fixed, 2049, true); // exceeded payload, throw
validate_size<PKTSTREAM>(grow, 2048, false); // succeeds validate_size<PKTSTREAM>(grow, 2048, false); // succeeds

View File

@ -391,7 +391,7 @@ class TestProto : public ProtoContextCallbackInterface
{ {
proto_context.start(); proto_context.start();
const size_t msglen = std::strlen(msg) + 1; const size_t msglen = std::strlen(msg) + 1;
templ.reset(new BufferAllocated((unsigned char *)msg, msglen, 0)); templ = BufferAllocatedRc::Create((unsigned char *)msg, msglen, 0);
proto_context.flush(true); proto_context.flush(true);
} }
@ -434,7 +434,7 @@ class TestProto : public ProtoContextCallbackInterface
BufferPtr data_encrypt_string(const char *str) BufferPtr data_encrypt_string(const char *str)
{ {
BufferPtr bp = new BufferAllocated(); BufferPtr bp = BufferAllocatedRc::Create();
frame->prepare(Frame::READ_LINK_UDP, *bp); frame->prepare(Frame::READ_LINK_UDP, *bp);
bp->write((unsigned char *)str, std::strlen(str)); bp->write((unsigned char *)str, std::strlen(str));
data_encrypt(*bp); data_encrypt(*bp);
@ -512,7 +512,7 @@ class TestProto : public ProtoContextCallbackInterface
if (disable_xmit_) if (disable_xmit_)
return; return;
net_bytes_ += net_buf.size(); net_bytes_ += net_buf.size();
net_out.push_back(BufferPtr(new BufferAllocated(net_buf, 0))); net_out.push_back(BufferAllocatedRc::Create(net_buf, 0));
} }
void control_recv(BufferPtr &&app_bp) override void control_recv(BufferPtr &&app_bp) override
@ -1349,12 +1349,12 @@ TEST(proto, controlmessage_invalidchar)
std::string only_whitespace{"\n\n\r\n\r\n\r\n"}; std::string only_whitespace{"\n\n\r\n\r\n\r\n"};
std::string empty{""}; std::string empty{""};
BufferAllocated valid_auth_fail_buf{reinterpret_cast<const unsigned char *>(valid_auth_fail.c_str()), valid_auth_fail.size(), BufferAllocated::GROW}; BufferAllocated valid_auth_fail_buf{reinterpret_cast<const unsigned char *>(valid_auth_fail.c_str()), valid_auth_fail.size(), BufAllocFlags::GROW};
BufferAllocated valid_auth_fail_newline_end_buf{reinterpret_cast<const unsigned char *>(valid_auth_fail_newline_end.c_str()), valid_auth_fail_newline_end.size(), BufferAllocated::GROW}; BufferAllocated valid_auth_fail_newline_end_buf{reinterpret_cast<const unsigned char *>(valid_auth_fail_newline_end.c_str()), valid_auth_fail_newline_end.size(), BufAllocFlags::GROW};
BufferAllocated invalid_auth_fail_buf{reinterpret_cast<const unsigned char *>(invalid_auth_fail.c_str()), invalid_auth_fail.size(), BufferAllocated::GROW}; BufferAllocated invalid_auth_fail_buf{reinterpret_cast<const unsigned char *>(invalid_auth_fail.c_str()), invalid_auth_fail.size(), BufAllocFlags::GROW};
BufferAllocated lot_of_whitespace_buf{reinterpret_cast<const unsigned char *>(lot_of_whitespace.c_str()), lot_of_whitespace.size(), BufferAllocated::GROW}; BufferAllocated lot_of_whitespace_buf{reinterpret_cast<const unsigned char *>(lot_of_whitespace.c_str()), lot_of_whitespace.size(), BufAllocFlags::GROW};
BufferAllocated only_whitespace_buf{reinterpret_cast<const unsigned char *>(only_whitespace.c_str()), only_whitespace.size(), BufferAllocated::GROW}; BufferAllocated only_whitespace_buf{reinterpret_cast<const unsigned char *>(only_whitespace.c_str()), only_whitespace.size(), BufAllocFlags::GROW};
BufferAllocated empty_buf{reinterpret_cast<const unsigned char *>(empty.c_str()), empty.size(), BufferAllocated::GROW}; BufferAllocated empty_buf{reinterpret_cast<const unsigned char *>(empty.c_str()), empty.size(), BufAllocFlags::GROW};
auto msg = ProtoContext::read_control_string<std::string>(valid_auth_fail_buf); auto msg = ProtoContext::read_control_string<std::string>(valid_auth_fail_buf);
EXPECT_EQ(msg, valid_auth_fail); EXPECT_EQ(msg, valid_auth_fail);

View File

@ -248,7 +248,7 @@ void test(MTRand &rand,
std::ostringstream os; std::ostringstream os;
os << "Test packet #" << count; os << "Test packet #" << count;
const std::string s = os.str(); const std::string s = os.str();
BufferPtr buffer(new BufferAllocated((unsigned char *)s.c_str(), s.length() + 1, 0)); auto buffer = BufferAllocatedRc::Create((unsigned char *)s.c_str(), s.length() + 1, 0);
ReliableSend::Message &m = send.send(now, Time::Duration()); ReliableSend::Message &m = send.send(now, Time::Duration());
m.packet.buf = buffer; m.packet.buf = buffer;
Message msg; Message msg;