OpenVPN 3 Core Library
Loading...
Searching...
No Matches
lz4.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12#pragma once
13
14#include <cstdint> // for std::uint32_t, uint64_t, etc.
15
16#include <lz4.h>
17
20#include <openvpn/common/socktypes.hpp> // for ntohl/htonl
22
24
25namespace openvpn::LZ4 {
26
28
29inline BufferPtr compress(const ConstBuffer &src,
30 const size_t headroom,
31 const size_t tailroom)
32{
33 // sanity check
34 if (src.size() > LZ4_MAX_INPUT_SIZE)
35 OPENVPN_THROW(lz4_error, "compress buffer size=" << src.size() << " exceeds LZ4_MAX_INPUT_SIZE=" << LZ4_MAX_INPUT_SIZE);
36
37 // allocate dest buffer
38 auto dest = BufferAllocatedRc::Create(sizeof(std::uint32_t) + headroom + tailroom + LZ4_COMPRESSBOUND(src.size()));
39 dest->init_headroom(headroom);
40
41 // as a hint to receiver, write the decompressed size
42 {
43 const std::uint32_t size = htonl(clamp_to_typerange<uint32_t>(src.size()));
44 dest->write(&size, sizeof(size));
45 }
46
47 // compress
48 const int comp_size = ::LZ4_compress_default((const char *)src.c_data(),
49 (char *)dest->data_end(),
50 (int)src.size(),
51 (int)dest->remaining(tailroom));
52 if (comp_size <= 0)
53 OPENVPN_THROW(lz4_error, "LZ4_compress_default returned error status=" << comp_size);
54 dest->inc_size(comp_size);
55 return dest;
56}
57
58inline BufferPtr decompress(const ConstBuffer &source,
59 const size_t headroom,
60 const size_t tailroom,
61 size_t max_decompressed_size = LZ4_MAX_INPUT_SIZE)
62{
63 // get the decompressed size
64 ConstBuffer src(source);
65 if (src.size() < sizeof(std::uint32_t))
66 OPENVPN_THROW(lz4_error, "decompress buffer size=" << src.size() << " is too small");
67 std::uint32_t size;
68 src.read(&size, sizeof(size));
69 size = ntohl(size);
70 if (max_decompressed_size > LZ4_MAX_INPUT_SIZE)
71 max_decompressed_size = LZ4_MAX_INPUT_SIZE;
72 if (max_decompressed_size && size > max_decompressed_size)
73 OPENVPN_THROW(lz4_error, "decompress expansion size=" << size << " is too large (must be <= " << max_decompressed_size << ')');
74
75 // allocate dest buffer
76 auto dest = BufferAllocatedRc::Create(headroom + tailroom + size);
77 dest->init_headroom(headroom);
78
79 // decompress
80 const int decomp_size = LZ4_decompress_safe((const char *)src.c_data(),
81 (char *)dest->data(),
82 (int)src.size(),
83 size);
84 if (decomp_size <= 0)
85 OPENVPN_THROW(lz4_error, "LZ4_decompress_safe returned error status=" << decomp_size);
86 if (static_cast<unsigned int>(decomp_size) != size)
87 OPENVPN_THROW(lz4_error, "decompress size inconsistency expected_size=" << size << " actual_size=" << decomp_size);
88 dest->inc_size(decomp_size);
89 return dest;
90}
91
92} // namespace openvpn::LZ4
const T * c_data() const
Returns a const pointer to the start of the buffer.
Definition buffer.hpp:1194
size_t size() const
Returns the size of the buffer in T objects.
Definition buffer.hpp:1242
void read(NCT *data, const size_t size)
Read data from the buffer into the specified memory location.
Definition buffer.hpp:1331
static Ptr Create(ArgsT &&...args)
Creates a new instance of RcEnable with the given arguments.
Definition make_rc.hpp:43
#define OPENVPN_EXCEPTION(C)
#define OPENVPN_THROW(exc, stuff)
BufferPtr compress(const ConstBuffer &src, const size_t headroom, const size_t tailroom)
Definition lz4.hpp:29
BufferPtr decompress(const ConstBuffer &source, const size_t headroom, const size_t tailroom, size_t max_decompressed_size=LZ4_MAX_INPUT_SIZE)
Definition lz4.hpp:58
OutT clamp_to_typerange(InT inVal)
Clamps the input value to the legal range for the output type.