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#ifndef OPENVPN_COMPRESS_LZ4_H
13#define OPENVPN_COMPRESS_LZ4_H
14
15// Implement LZ4 compression.
16// Should only be included by compress.hpp
17
18#include <algorithm> // for std::max
19
21
22#include <lz4.h>
23
24namespace openvpn {
25
27{
28 protected:
33
35 {
36 auto prepRes = frame->prepare(Frame::DECOMPRESS_WORK, work);
37 if (!numeric_util::is_safe_conversion<const int>(prepRes))
38 return false;
39
40 // initialize work buffer
41 auto payload_size = static_cast<const int>(prepRes);
42
43 // do uncompress
44 const int decomp_size = LZ4_decompress_safe((const char *)buf.c_data(),
45 (char *)work.data(),
46 (int)buf.size(),
47 payload_size);
48 if (decomp_size < 0)
49 {
50 error(buf);
51 return false;
52 }
53 OVPN_LOG_VERBOSE("LZ4 uncompress " << buf.size() << " -> " << decomp_size);
54 work.set_size(decomp_size);
55 buf.swap(work);
56 return true;
57 }
58
60 {
61 // initialize work buffer
63
64 // verify that input data length is not too large
65 if (lz4_extra_buffer(buf.size()) > work.max_size())
66 {
67 error(buf);
68 return false;
69 }
70
71 // do compress
72 const unsigned int comp_size = LZ4_compress_default((const char *)buf.c_data(),
73 (char *)work.data(),
74 (int)buf.size(),
75 (int)work.capacity());
76
77 // did compression actually reduce data length?
78 if (comp_size < buf.size())
79 {
80 if (comp_size <= 0)
81 {
82 error(buf);
83 return false;
84 }
85 OVPN_LOG_VERBOSE("LZ4 compress " << buf.size() << " -> " << comp_size);
86 work.set_size(comp_size);
87 buf.swap(work);
88 return true;
89 }
90 return false;
91 }
92
93 // Worst case size expansion on compress.
94 // Official LZ4 worst-case size expansion alg is
95 // LZ4_COMPRESSBOUND macro in lz4.h.
96 // However we optimize it slightly here to lose the integer division
97 // when len < 65535.
98 size_t lz4_extra_buffer(const size_t len)
99 {
100 if (likely(len < 65535))
101 return len + len / 256 + 17;
102 return len + len / 255 + 16;
103 }
104
106};
107
109{
110 // magic number for LZ4 compression
111 enum
112 {
114 };
115
116 public:
117 CompressLZ4(const Frame::Ptr &frame, const SessionStats::Ptr &stats, const bool asym_arg)
119 asym(asym_arg)
120 {
121 OVPN_LOG_INFO("LZ4 init asym=" << asym_arg);
122 }
123
124 const char *name() const override
125 {
126 return "lz4";
127 }
128
129 void compress(BufferAllocated &buf, const bool hint) override
130 {
131 // skip null packets
132 if (buf.empty())
133 return;
134
135 if (hint && !asym)
136 {
137 if (do_compress(buf))
138 {
139 do_swap(buf, LZ4_COMPRESS);
140 return;
141 }
142 }
143
144 // indicate that we didn't compress
146 }
147
148 void decompress(BufferAllocated &buf) override
149 {
150 // skip null packets
151 if (buf.empty())
152 return;
153
154 const unsigned char c = buf.pop_front();
155 switch (c)
156 {
157 case NO_COMPRESS_SWAP:
158 do_unswap(buf);
159 break;
160 case LZ4_COMPRESS:
161 do_unswap(buf);
162 do_decompress(buf);
163 break;
164 default:
165 error(buf); // unknown op
166 }
167 }
168
169 private:
170 const bool asym;
171};
172
174{
175 public:
176 CompressLZ4v2(const Frame::Ptr &frame, const SessionStats::Ptr &stats, const bool asym_arg)
178 asym(asym_arg)
179 {
180 OVPN_LOG_INFO("LZ4v2 init asym=" << asym_arg);
181 }
182
183 const char *name() const override
184 {
185 return "lz4v2";
186 }
187
188 void compress(BufferAllocated &buf, const bool hint) override
189 {
190 // skip null packets
191 if (buf.empty())
192 return;
193
194 if (hint && !asym)
195 {
196 if (do_compress(buf))
197 {
199 return;
200 }
201 }
202
203 // indicate that we didn't compress
205 }
206
207 void decompress(BufferAllocated &buf) override
208 {
209 // skip null packets
210 if (buf.empty())
211 return;
212
213 const int c = v2_pull(buf);
214 switch (c)
215 {
216 case OVPN_COMPv2_NONE:
217 break;
218 case OVPN_COMPv2_LZ4:
219 do_decompress(buf);
220 break;
221 default:
222 error(buf); // unknown op
223 }
224 }
225
226 private:
227 const bool asym;
228};
229
230} // namespace openvpn
231
232#endif
void swap(BufferAllocatedType< T_ > &other)
Swaps the contents of this BufferAllocatedType object with another BufferAllocatedType object.
Definition buffer.hpp:1796
CompressLZ4Base(const Frame::Ptr &frame, const SessionStats::Ptr &stats)
Definition lz4.hpp:29
bool do_decompress(BufferAllocated &buf)
Definition lz4.hpp:34
bool do_compress(BufferAllocated &buf)
Definition lz4.hpp:59
BufferAllocated work
Definition lz4.hpp:105
size_t lz4_extra_buffer(const size_t len)
Definition lz4.hpp:98
void compress(BufferAllocated &buf, const bool hint) override
Definition lz4.hpp:129
CompressLZ4(const Frame::Ptr &frame, const SessionStats::Ptr &stats, const bool asym_arg)
Definition lz4.hpp:117
const char * name() const override
Definition lz4.hpp:124
const bool asym
Definition lz4.hpp:170
void decompress(BufferAllocated &buf) override
Definition lz4.hpp:148
const char * name() const override
Definition lz4.hpp:183
const bool asym
Definition lz4.hpp:227
void compress(BufferAllocated &buf, const bool hint) override
Definition lz4.hpp:188
CompressLZ4v2(const Frame::Ptr &frame, const SessionStats::Ptr &stats, const bool asym_arg)
Definition lz4.hpp:176
void decompress(BufferAllocated &buf) override
Definition lz4.hpp:207
void do_swap(Buffer &buf, unsigned char op)
Definition compress.hpp:82
void error(BufferAllocated &buf)
Definition compress.hpp:76
void do_unswap(Buffer &buf)
Definition compress.hpp:93
void v2_push(Buffer &buf, unsigned char value)
Definition compress.hpp:104
Frame::Ptr frame
Definition compress.hpp:127
SessionStats::Ptr stats
Definition compress.hpp:128
int v2_pull(Buffer &buf)
Definition compress.hpp:117
const T * c_data() const
Returns a const pointer to the start of the buffer.
Definition buffer.hpp:1193
size_t max_size() const
Return the maximum allowable size value in T objects given the current offset (without considering re...
Definition buffer.hpp:1374
size_t capacity() const
Returns the capacity (raw size) of the allocated buffer in T objects.
Definition buffer.hpp:1211
size_t size() const
Returns the size of the buffer in T objects.
Definition buffer.hpp:1241
T * data()
Get a mutable pointer to the start of the array.
Definition buffer.hpp:1447
bool empty() const
Returns true if the buffer is empty.
Definition buffer.hpp:1235
T pop_front()
Removes and returns the first element from the buffer.
Definition buffer.hpp:1255
void set_size(const size_t size)
After an external method, operating on the array as a mutable unsigned char buffer,...
Definition buffer.hpp:1381
size_t prepare(const unsigned int context, Buffer &buf) const
Definition frame.hpp:263
#define likely(x)
Definition likely.hpp:21
#define OVPN_LOG_INFO(args)
Definition logger.hpp:224
#define OVPN_LOG_VERBOSE(args)
Definition logger.hpp:225