0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-19 11:42: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 *`.
* 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
protect against security bugs that arise when using raw buffer pointers.
See `<openvpn/buffer/buffer.hpp>`_ for the OpenVPN :code:`Buffer` classes.

View File

@ -32,7 +32,7 @@
namespace openvpn::CF {
// 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)
{

View File

@ -45,7 +45,7 @@
// 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
// 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
@ -63,6 +63,7 @@
#include <openvpn/common/exception.hpp>
#include <openvpn/common/rc.hpp>
#include <openvpn/buffer/bufclamp.hpp>
#include <openvpn/common/make_rc.hpp>
#ifdef OPENVPN_BUFFER_ABORT
#define OPENVPN_BUFFER_THROW(exc) \
@ -204,7 +205,7 @@ class BufferException : public std::exception
// ===============================================================================================
// ===============================================================================================
template <typename T, typename R>
template <typename T>
class BufferAllocatedType;
template <typename T>
@ -868,12 +869,24 @@ class BufferType : public ConstBufferType<T>
// class BufferAllocatedType
// ===============================================================================================
template <typename T, typename R>
class BufferAllocatedType : public BufferType<T>, public RC<R>
// Allocation and security for the buffer
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:
// Friend to all specializations of this template allows access to other.data_
template <typename, typename>
template <typename>
friend class BufferAllocatedType;
public:
@ -888,14 +901,6 @@ class BufferAllocatedType : public BufferType<T>, public RC<R>
using BufferType<T>::c_data;
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.
*/
@ -979,14 +984,8 @@ class BufferAllocatedType : public BufferType<T>, public RC<R>
* @tparam R_ The template parameter type of the other BufferAllocatedType object.
* @param other The other BufferAllocatedType object to move from.
*/
template <typename T_, typename R_>
void move(BufferAllocatedType<T_, R_> &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();
template <typename T_>
void move(BufferAllocatedType<T_> &other);
/**
* @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.
* @param other The other BufferAllocatedType object to swap with.
*/
template <typename T_, typename R_>
void swap(BufferAllocatedType<T_, R_> &other);
template <typename T_>
void swap(BufferAllocatedType<T_> &other);
/**
* @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.
* @param other The other BufferAllocatedType object to move from.
*/
template <typename T_, typename R_>
BufferAllocatedType(BufferAllocatedType<T_, R_> &&other) noexcept;
template <typename T_>
BufferAllocatedType(BufferAllocatedType<T_> &&other) noexcept;
/**
* @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){};
// ===============================================================================================
// BufferAllocatedType<T, R> member function definitions
// BufferAllocatedType<T> member function definitions
// ===============================================================================================
template <typename T, typename R>
BufferAllocatedType<T, R>::BufferAllocatedType(const size_t offset, const size_t size, const size_t capacity, const unsigned int flags)
template <typename T>
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)
{
if (flags & CONSTRUCT_ZERO)
if (flags & BufAllocFlags::CONSTRUCT_ZERO)
std::memset(data_raw(), 0, capacity * sizeof(T));
}
template <typename T, typename R>
BufferAllocatedType<T, R>::BufferAllocatedType()
template <typename T>
BufferAllocatedType<T>::BufferAllocatedType()
: BufferAllocatedType(0, 0, 0, 0)
{
static_assert(std::is_nothrow_move_constructible_v<BufferAllocatedType>,
"class BufferAllocatedType not noexcept move constructable");
}
template <typename T, typename R>
BufferAllocatedType<T, R>::BufferAllocatedType(const size_t capacity, const unsigned int flags)
: BufferAllocatedType(0, flags & ARRAY ? capacity : 0, capacity, flags){};
template <typename T>
BufferAllocatedType<T>::BufferAllocatedType(const size_t capacity, const unsigned int flags)
: BufferAllocatedType(0, flags & BufAllocFlags::ARRAY ? capacity : 0, capacity, flags){};
template <typename T, typename R>
BufferAllocatedType<T, R>::BufferAllocatedType(const T *data, const size_t size, const unsigned int flags)
template <typename T>
BufferAllocatedType<T>::BufferAllocatedType(const T *data, const size_t size, const unsigned int flags)
: BufferAllocatedType(0, size, size, flags)
{
if (size)
if (size && data)
std::memcpy(data_raw(), data, size * sizeof(T));
}
template <typename T, typename R>
BufferAllocatedType<T, R>::BufferAllocatedType(const BufferAllocatedType &other)
template <typename T>
BufferAllocatedType<T>::BufferAllocatedType(const BufferAllocatedType &other)
: BufferAllocatedType(other.offset(), other.size(), other.capacity(), other.flags_)
{
if (size())
std::memcpy(data(), other.c_data(), size() * sizeof(T));
}
template <typename T, typename R>
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)
{
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));
}
template <typename T, typename R>
void BufferAllocatedType<T, R>::operator=(const BufferAllocatedType &other)
template <typename T>
void BufferAllocatedType<T>::operator=(const BufferAllocatedType &other)
{
if (this != &other)
{
@ -1702,74 +1701,68 @@ void BufferAllocatedType<T, R>::operator=(const BufferAllocatedType &other)
}
}
template <typename T, typename R>
void BufferAllocatedType<T, R>::init(const size_t capacity, const unsigned int flags)
template <typename T>
void BufferAllocatedType<T>::init(const size_t capacity, const unsigned int flags)
{
auto tempBuffer = BufferAllocatedType(capacity, flags);
swap(tempBuffer);
}
template <typename T, typename R>
void BufferAllocatedType<T, R>::init(const T *data, const size_t size, const unsigned int flags)
template <typename T>
void BufferAllocatedType<T>::init(const T *data, const size_t size, const unsigned int flags)
{
auto tempBuffer = BufferAllocatedType(data, size, flags);
swap(tempBuffer);
}
template <typename T, typename R>
void BufferAllocatedType<T, R>::realloc(const size_t newcap)
template <typename T>
void BufferAllocatedType<T>::realloc(const size_t newcap)
{
if (newcap > capacity())
realloc_(newcap);
}
template <typename T, typename R>
void BufferAllocatedType<T, R>::reset(const size_t min_capacity, const unsigned int flags)
template <typename T>
void BufferAllocatedType<T>::reset(const size_t min_capacity, const unsigned int flags)
{
if (min_capacity > capacity())
init(min_capacity, flags);
}
template <typename T, typename R>
void BufferAllocatedType<T, R>::reset(const size_t headroom, const size_t min_capacity, const unsigned int flags)
template <typename T>
void BufferAllocatedType<T>::reset(const size_t headroom, const size_t min_capacity, const unsigned int flags)
{
reset(min_capacity, flags);
init_headroom(headroom);
}
template <typename T, typename R>
template <typename T_, typename R_>
void BufferAllocatedType<T, R>::move(BufferAllocatedType<T_, R_> &other)
template <typename T>
template <typename T_>
void BufferAllocatedType<T>::move(BufferAllocatedType<T_> &other)
{
auto temp = BufferAllocatedType();
swap(other);
other.swap(temp);
}
template <typename T, typename R>
RCPtr<BufferAllocatedType<T, R>> BufferAllocatedType<T, R>::move_to_ptr()
{
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)
template <typename T>
template <typename T_>
void BufferAllocatedType<T>::swap(BufferAllocatedType<T_> &other)
{
BufferType<T>::swap(other);
std::swap(flags_, other.flags_);
}
template <typename T, typename R>
template <typename T_, typename R_>
BufferAllocatedType<T, R>::BufferAllocatedType(BufferAllocatedType<T_, R_> &&other) noexcept
template <typename T>
template <typename T_>
BufferAllocatedType<T>::BufferAllocatedType(BufferAllocatedType<T_> &&other) noexcept
: BufferAllocatedType()
{
move(other);
}
template <typename T, typename R>
BufferAllocatedType<T, R> &BufferAllocatedType<T, R>::operator=(BufferAllocatedType &&other) noexcept
template <typename T>
BufferAllocatedType<T> &BufferAllocatedType<T>::operator=(BufferAllocatedType &&other) noexcept
{
if (this != &other)
{
@ -1778,53 +1771,53 @@ BufferAllocatedType<T, R> &BufferAllocatedType<T, R>::operator=(BufferAllocatedT
return *this;
}
template <typename T, typename R>
void BufferAllocatedType<T, R>::clear()
template <typename T>
void BufferAllocatedType<T>::clear()
{
auto tempBuffer = BufferAllocatedType(0, 0, 0, 0);
swap(tempBuffer);
}
template <typename T, typename R>
void BufferAllocatedType<T, R>::or_flags(const unsigned int flags)
template <typename T>
void BufferAllocatedType<T>::or_flags(const unsigned int flags)
{
flags_ |= flags;
}
template <typename T, typename R>
void BufferAllocatedType<T, R>::and_flags(const unsigned int flags)
template <typename T>
void BufferAllocatedType<T>::and_flags(const unsigned int flags)
{
flags_ &= flags;
}
template <typename T, typename R>
BufferAllocatedType<T, R>::~BufferAllocatedType()
template <typename T>
BufferAllocatedType<T>::~BufferAllocatedType()
{
if (data_raw())
free_data();
}
template <typename T, typename R>
void BufferAllocatedType<T, R>::reset_impl(const size_t min_capacity, const unsigned int flags)
template <typename T>
void BufferAllocatedType<T>::reset_impl(const size_t min_capacity, const unsigned int flags)
{
init(min_capacity, flags);
}
template <typename T, typename R>
void BufferAllocatedType<T, R>::resize(const size_t new_capacity)
template <typename T>
void BufferAllocatedType<T>::resize(const size_t new_capacity)
{
const size_t newcap = std::max(new_capacity, capacity() * 2);
if (newcap > capacity())
{
if (flags_ & GROW)
if (flags_ & BufAllocFlags::GROW)
realloc_(newcap);
else
buffer_full_error(newcap, true);
}
}
template <typename T, typename R>
void BufferAllocatedType<T, R>::realloc_(const size_t newcap)
template <typename T>
void BufferAllocatedType<T>::realloc_(const size_t newcap)
{
auto tempBuffer = BufferAllocatedType(offset(), size(), newcap, flags_);
if (size())
@ -1832,10 +1825,10 @@ void BufferAllocatedType<T, R>::realloc_(const size_t newcap)
swap(tempBuffer);
}
template <typename T, typename R>
void BufferAllocatedType<T, R>::free_data()
template <typename T>
void BufferAllocatedType<T>::free_data()
{
if (size() && (flags_ & DESTRUCT_ZERO))
if (size() && (flags_ & BufAllocFlags::DESTRUCT_ZERO))
std::memset(data_raw(), 0, capacity() * sizeof(T));
delete[] data_raw();
}
@ -1844,17 +1837,18 @@ void BufferAllocatedType<T, R>::free_data()
// specializations of BufferType for unsigned char
// ===============================================================================================
typedef BufferType<unsigned char> Buffer;
typedef ConstBufferType<unsigned char> ConstBuffer;
typedef BufferAllocatedType<unsigned char, thread_unsafe_refcount> BufferAllocated;
typedef RCPtr<BufferAllocated> BufferPtr;
using Buffer = BufferType<unsigned char>;
using ConstBuffer = ConstBufferType<unsigned char>;
using BufferAllocated = BufferAllocatedType<unsigned char>;
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;
typedef RCPtr<BufferAllocatedTS> BufferPtrTS;
using BufferAllocatedTS = RcEnable<BufferAllocated, RC<thread_safe_refcount>>;
using BufferPtrTS = RCPtr<BufferAllocatedTS>;
// ===============================================================================================
// cast BufferType<T> to ConstBufferType<T>

View File

@ -56,7 +56,7 @@ struct BufferCollection : public COLLECTION<BufferPtr>
const size_t size = join_size();
// allocate buffer
BufferPtr big = new BufferAllocated(size + headroom + tailroom, 0);
auto big = BufferAllocatedRc::Create(size + headroom + tailroom, 0);
big->init_headroom(headroom);
// second pass -- copy data
@ -89,7 +89,7 @@ struct BufferCollection : public COLLECTION<BufferPtr>
{
BufferCollection ret;
for (auto &b : *this)
ret.emplace_back(new BufferAllocated(*b));
ret.emplace_back(BufferAllocatedRc::Create(*b));
return ret;
}
@ -111,7 +111,7 @@ struct BufferCollection : public COLLECTION<BufferPtr>
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)
{
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);
return buf;
}
@ -65,7 +65,7 @@ inline BufferPtr buf_from_string(const std::string &str)
inline BufferPtr buf_from_string(const char *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);
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);
// 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);
// 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 << ')');
// allocate dest buffer
BufferPtr dest = new BufferAllocated(headroom + tailroom + size, 0);
auto dest = BufferAllocatedRc::Create(headroom + tailroom + size, 0);
dest->init_headroom(headroom);
// decompress

View File

@ -30,10 +30,13 @@
#include <openvpn/buffer/bufstr.hpp>
namespace openvpn {
/**
@brief A string-like type that clears the buffer contents on delete
*/
class SafeString
{
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:
SafeString()

View File

@ -90,7 +90,7 @@ inline BufferPtr compress_gzip(BufferPtr src,
if (status != Z_OK)
OPENVPN_THROW(zlib_error, "zlib deflateinit2 failed, error=" << status);
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);
zs.s.next_out = b->data();
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
// 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);
const size_t avail = b->remaining(tr);
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();
if (msg)
{
api.write_ciphertext(new BufferAllocated(reinterpret_cast<const unsigned char *>(msg->c_str()),
msg->size(),
0));
api.write_ciphertext(BufferAllocatedRc::Create(reinterpret_cast<const unsigned char *>(msg->c_str()),
msg->size(),
0));
// Won't handshake without this even though there is no data available.
uint8_t cleartext[8];

View File

@ -416,7 +416,7 @@ struct InfoJSON : public Base
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, ":");
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);
// 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
ifs.read((char *)b->data(), length);
@ -114,7 +114,7 @@ inline BufferPtr read_binary_linear(const std::string &filename,
std::streamsize total_size = 0;
while (true)
{
BufferPtr b = new BufferAllocated(block_size, 0);
auto b = BufferAllocatedRc::Create(block_size, 0);
ifs.read((char *)b->data(), b->remaining());
const std::streamsize size = ifs.gcount();
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) + ']');
// 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
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,
StrongRandomAPI &rng)
{
BufferPtr bp = new BufferAllocated(size_hint, BufferAllocated::GROW);
auto bp = BufferAllocatedRc::Create(size_hint, BufAllocFlags::GROW);
format_compact(root, *bp);
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 size_t size_hint)
{
BufferPtr bp = new BufferAllocated(size_hint, BufferAllocated::GROW);
auto bp = BufferAllocatedRc::Create(size_hint, BufAllocFlags::GROW);
format_compact(root, *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);
dest = clamp_notify<unsigned char>(temp,
[](decltype(temp) temp) -> unsigned char
{
{
auto why = std::string("Conversion error [" + std::to_string(temp) + "] to unsigned char");
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,
const size_t size_hint = 256)
{
BufferPtr bp = new BufferAllocated(size_hint, BufferAllocated::GROW);
format_compact(root, *bp);
return buf_to_string(*bp);
auto bp = BufferAllocated(size_hint, BufAllocFlags::GROW);
format_compact(root, bp);
return buf_to_string(bp);
}
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(),
lenientConversion);
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();
for (const UTF16 *s = utf16_dest.get(); s < dest; ++s)
{

View File

@ -51,7 +51,7 @@ class CompressLZO : public Compress
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()

View File

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

View File

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

View File

@ -47,7 +47,7 @@ class StaticKey
{
}
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)
{
key_data_.reset(capacity, key_t::DESTRUCT_ZERO);
key_data_.reset(capacity, BufAllocFlags::DESTRUCT_ZERO);
base64->decode(key_data_, b64);
}
@ -82,7 +82,7 @@ class StaticKey
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);
key_data_.set_size(key_size);
}
@ -151,7 +151,7 @@ class OpenVPNStaticKey
void parse(const std::string &key_text)
{
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;
while (in(true))
{
@ -182,7 +182,7 @@ class OpenVPNStaticKey
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();
}

View File

@ -45,7 +45,7 @@ class TLSCryptV2ServerKey
TLSCryptV2ServerKey()
: 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)
{
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))
throw tls_crypt_v2_client_key_parse_error();
@ -119,8 +119,8 @@ class TLSCryptV2ClientKey
if (data.size() < (tag_size + key_size))
throw tls_crypt_v2_client_key_bad_size();
key.init(data.data(), key_size, BufferAllocated::DESTRUCT_ZERO);
wkc.init(data.data() + key_size, data.size() - key_size, BufferAllocated::DESTRUCT_ZERO);
key.init(data.data(), key_size, BufAllocFlags::DESTRUCT_ZERO);
wkc.init(data.data() + key_size, data.size() - key_size, BufAllocFlags::DESTRUCT_ZERO);
}
void extract_key(OpenVPNStaticKey &tls_key)
@ -131,7 +131,7 @@ class TLSCryptV2ClientKey
std::string render() const
{
BufferAllocated data(32 + 2 * (key.size() + wkc.size()), 0);
BufferAllocated in(key, BufferAllocated::GROW);
BufferAllocated in(key, BufAllocFlags::GROW);
in.append(wkc);
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
pkt->buf.reset(512,
3072,
BufferAllocated::GROW | BufferAllocated::CONSTRUCT_ZERO | BufferAllocated::DESTRUCT_ZERO);
BufAllocFlags::GROW | BufAllocFlags::CONSTRUCT_ZERO | BufAllocFlags::DESTRUCT_ZERO);
pipe->async_read_some(
pkt->buf.mutable_buffer(),
[self = Ptr(this),

View File

@ -84,7 +84,7 @@ class Frame : public RC<thread_unsafe_refcount>
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_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;
payload_ = payload;
@ -144,11 +144,11 @@ class Frame : public RC<thread_unsafe_refcount>
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
{
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->write(data, size);
return b;
@ -164,13 +164,13 @@ class Frame : public RC<thread_unsafe_refcount>
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.
BufferPtr copy(const BufferPtr &buf) const
{
const size_t size = buf ? buf->size() : 0;
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()));
if (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 buf(new BufferAllocated());
auto buf = BufferAllocatedRc::Create();
prepare(context, *buf);
return buf;
}

View File

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

View File

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

View File

@ -80,7 +80,7 @@ class MbedTLSPEM
{
size_t buflen = 0;
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);

View File

@ -930,7 +930,7 @@ class OMICore : public Acceptor::ListenerBase
{
if (!is_sock_open() || recv_queued)
return;
BufferPtr buf(new BufferAllocated(256, 0));
BufferPtr buf = BufferAllocatedRc::Create(256, 0);
socket->async_receive(buf->mutable_buffer_clamp(),
[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())
return;
BufferAllocated &buf = *content_out.front();
auto &buf = *content_out.front();
socket->async_send(buf.const_buffer_clamp(),
[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();
// allocate return buffer
BufferPtr ret(new BufferAllocated(total_size, 0));
auto ret = BufferAllocatedRc::Create(total_size, 0);
buf_append_string(*ret, "PUSH_REPLY");
// terminators
@ -163,7 +163,7 @@ class PushContinuationFragment : public std::vector<BufferPtr>
void append_new_buffer()
{
// 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");
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
{
if (buf.defined())
in.emplace_back(new BufferAllocated(std::move(buf)));
in.emplace_back(BufferAllocatedRc::Create(std::move(buf)));
}
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
{
if (buf.defined())
in.emplace_back(new BufferAllocated(std::move(buf)));
in.emplace_back(BufferAllocatedRc::Create(std::move(buf)));
}
BufferPtr http_content_out() override

View File

@ -152,7 +152,7 @@ class NTLM
std::memcpy(ntlmv2_response, ntlmv2_hmacmd5, 16);
// 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
phase3[8] = 3; // type 3

View File

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

View File

@ -183,7 +183,7 @@ class AppControlMessageReceiver
bool receive_message(const std::string &msg)
{
if (!recvbuf.defined())
recvbuf.reset(256, BufferAllocated::GROW);
recvbuf.reset(256, BufAllocFlags::GROW);
// msg includes ACC, prefix
auto parts = string::split(msg, ',', 4);
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)
{
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);
control_send(std::move(bp));
}
@ -1623,7 +1623,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
{
Packet pkt;
pkt.opcode = opcode;
pkt.buf.reset(new BufferAllocated(*buf));
pkt.buf = BufferAllocatedRc::Create(*buf);
return pkt;
}
@ -1636,7 +1636,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
void frame_prepare(const Frame &frame, const unsigned int context)
{
if (!buf)
buf.reset(new BufferAllocated());
buf = BufferAllocatedRc::Create();
frame.prepare(context, *buf);
}
@ -2864,7 +2864,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
void send_auth()
{
BufferPtr buf = new BufferAllocated();
auto buf = BufferAllocatedRc::Create();
proto.config->frame->prepare(Frame::WRITE_SSL_CLEARTEXT, *buf);
buf->write(proto_context_private::auth_prefix, sizeof(proto_context_private::auth_prefix));
tlsprf->self_randomize(*proto.config->rng);
@ -2874,7 +2874,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
if (!proto.is_server())
{
OVPN_LOG_INFO("Tunnel Options:" << options);
buf->or_flags(BufferAllocated::DESTRUCT_ZERO);
buf->or_flags(BufAllocFlags::DESTRUCT_ZERO);
if (proto.config->xmit_creds)
proto.client_auth(*buf);
else
@ -3223,7 +3223,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
bool decapsulate_tls_crypt(Packet &pkt)
{
BufferAllocated &recv = *pkt.buf;
auto &recv = *pkt.buf;
const unsigned char *orig_data = recv.data();
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)
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
// the WKc length in network order
wkc_len = htons(wkc_len);
@ -4096,7 +4096,7 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
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
@ -4109,14 +4109,14 @@ class ProtoContext : public logging::LoggingMixin<OPENVPN_DEBUG_PROTO,
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))
return false;
return select_key_context(type, true).net_recv(std::move(pkt));
}
// 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
bool control_net_recv(const PacketType &type, BufferPtr &&net_bp)
{

View File

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

View File

@ -156,7 +156,7 @@ class TLSPRF
+ client_seed_len
+ server_seed_len
+ ProtoSessionID::SIZE * 2,
BufferAllocated::DESTRUCT_ZERO);
BufAllocFlags::DESTRUCT_ZERO);
seed.write((unsigned char *)label, label_len);
seed.write(client_seed, client_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)
{
// 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.
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();
}

View File

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

View File

@ -219,7 +219,7 @@ class UDPLink : public RC<thread_unsafe_refcount>
std::unique_ptr<AsioEndpoint> ep;
if (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)
self->do_send(buf, ep.get()); });

View File

@ -755,7 +755,7 @@ class GeNL : public RC<thread_unsafe_refcount>
void reset_buffer()
{
// 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)
{
BufferAllocated v(4, BufferAllocated::CONSTRUCT_ZERO);
BufferAllocated v(4, BufAllocFlags::CONSTRUCT_ZERO);
parse_hex(v, hexaddr);
if (v.size() != 4)
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)
{
BufferAllocated v(4, BufferAllocated::CONSTRUCT_ZERO);
BufferAllocated v(4, BufAllocFlags::CONSTRUCT_ZERO);
parse_hex(v, hexaddr);
if (v.size() != 4)
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);
if (status != ERROR_SUCCESS)
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);
if (status == ERROR_SUCCESS)
@ -490,7 +490,7 @@ struct DeviceInstanceIdInterfaceList : public std::vector<DeviceInstanceIdInterf
if (res != FALSE && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
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))
continue;
buf_dev_inst_id.set_size(size);
@ -504,7 +504,7 @@ struct DeviceInstanceIdInterfaceList : public std::vector<DeviceInstanceIdInterf
if (cr != CR_SUCCESS)
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,
buf_dev_inst_id.data(),
buf_dev_iface_list.data(),

View File

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

View File

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

View File

@ -230,7 +230,7 @@ class HTTPBase : public REFCOUNT_BASE
if (ssl_sess)
{
// HTTPS
BufferPtr buf(new BufferAllocated());
auto buf = BufferAllocatedRc::Create();
buf->swap(b); // take ownership
ssl_sess->write_ciphertext(buf);
ssl_up_stack();
@ -252,10 +252,10 @@ class HTTPBase : public REFCOUNT_BASE
// void base_http_content_out_needed();
// void base_http_out_eof();
// bool base_http_headers_received();
// void base_http_content_in(BufferAllocated& buf);
// bool base_link_send(BufferAllocated& buf);
// void base_http_content_in(BufferAllocatedRc& buf);
// bool base_link_send(BufferAllocatedRc& buf);
// 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);
// protected member vars

View File

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

View File

@ -333,7 +333,7 @@ class Receiver
if (!buf.allocated())
{
buf = std::move(inbuf);
buf.or_flags(BufferAllocated::GROW);
buf.or_flags(BufAllocFlags::GROW);
}
else
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)>;
BufferAllocated signdata(256, BufferAllocated::GROW);
BufferAllocated signdata(256, BufAllocFlags::GROW);
base64->decode(signdata, signreq.data);
EVP_PKEY *pkey = epki_pkey.obj();
@ -572,7 +572,7 @@ class Client : public ClientBase
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)
{
@ -598,7 +598,7 @@ class Client : public ClientBase
void doOpenSSLDigestSignature(ClientAPI::ExternalPKISignRequest &signreq)
{
EVP_PKEY_CTX *pkey_ctx = nullptr;
BufferAllocated signdata(256, BufferAllocated::GROW);
BufferAllocated signdata(256, BufAllocFlags::GROW);
base64->decode(signdata, signreq.data);
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());
}
BufferAllocated sig(outlen, BufferAllocated::ARRAY);
BufferAllocated sig(outlen, BufAllocFlags::ARRAY);
if (EVP_DigestSign(md.get(), sig.data(), &outlen, signdata.data(), signdata.size()) < 0)
{
@ -694,7 +694,7 @@ class Client : public ClientBase
try
{
// decode base64 sign request
BufferAllocated signdata(256, BufferAllocated::GROW);
BufferAllocated signdata(256, BufAllocFlags::GROW);
base64->decode(signdata, signreq.data);
// 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));
// 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
size_t sig_size = 0;

View File

@ -74,6 +74,7 @@ add_executable(coreUnitTests
test_statickey.cpp
test_streq.cpp
test_time.cpp
test_make_rc.cpp
test_typeindex.cpp
test_tun_builder.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));
}
// test equality of BufferAllocated and ConstBuffer
// test equality of BufferAllocatedRc and ConstBuffer
TEST(buffer, const_buffer_ref_2)
{
BufferAllocated buf(64, 0);
@ -165,7 +165,7 @@ TEST(buffer, alloc_buffer_access1)
// Test read/write access and bounds check
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[0] = 'j';

View File

@ -129,7 +129,7 @@ static OptionList random_optionlist(RandomAPI &prng)
static void test_roundtrip(const OptionList &opt_orig)
{
// 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, opt_orig.render_csv());
@ -186,7 +186,7 @@ TEST(continuation, test1)
// push-list for further testing
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");
// 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;
#endif
const Frame::Context fc(256, 512, 256, 0, sizeof(size_t), grow ? BufferAllocated::GROW : 0);
const Frame::Context fc_big(256, 4096, 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 ? BufAllocFlags::GROW : 0);
if (verbose)
{
@ -172,7 +172,7 @@ static void validate_size_test()
const size_t tailroom = 0;
const size_t align_block = 16;
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, 2049, true); // exceeded payload, throw
validate_size<PKTSTREAM>(grow, 2048, false); // succeeds

View File

@ -391,7 +391,7 @@ class TestProto : public ProtoContextCallbackInterface
{
proto_context.start();
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);
}
@ -434,7 +434,7 @@ class TestProto : public ProtoContextCallbackInterface
BufferPtr data_encrypt_string(const char *str)
{
BufferPtr bp = new BufferAllocated();
BufferPtr bp = BufferAllocatedRc::Create();
frame->prepare(Frame::READ_LINK_UDP, *bp);
bp->write((unsigned char *)str, std::strlen(str));
data_encrypt(*bp);
@ -512,7 +512,7 @@ class TestProto : public ProtoContextCallbackInterface
if (disable_xmit_)
return;
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
@ -1349,12 +1349,12 @@ TEST(proto, controlmessage_invalidchar)
std::string only_whitespace{"\n\n\r\n\r\n\r\n"};
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_newline_end_buf{reinterpret_cast<const unsigned char *>(valid_auth_fail_newline_end.c_str()), valid_auth_fail_newline_end.size(), BufferAllocated::GROW};
BufferAllocated invalid_auth_fail_buf{reinterpret_cast<const unsigned char *>(invalid_auth_fail.c_str()), invalid_auth_fail.size(), BufferAllocated::GROW};
BufferAllocated lot_of_whitespace_buf{reinterpret_cast<const unsigned char *>(lot_of_whitespace.c_str()), lot_of_whitespace.size(), BufferAllocated::GROW};
BufferAllocated only_whitespace_buf{reinterpret_cast<const unsigned char *>(only_whitespace.c_str()), only_whitespace.size(), BufferAllocated::GROW};
BufferAllocated empty_buf{reinterpret_cast<const unsigned char *>(empty.c_str()), empty.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(), BufAllocFlags::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(), BufAllocFlags::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(), BufAllocFlags::GROW};
auto msg = ProtoContext::read_control_string<std::string>(valid_auth_fail_buf);
EXPECT_EQ(msg, valid_auth_fail);

View File

@ -248,7 +248,7 @@ void test(MTRand &rand,
std::ostringstream os;
os << "Test packet #" << count;
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());
m.packet.buf = buffer;
Message msg;