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 else
91 return false;
92 }
93
94 // Worst case size expansion on compress.
95 // Official LZ4 worst-case size expansion alg is
96 // LZ4_COMPRESSBOUND macro in lz4.h.
97 // However we optimize it slightly here to lose the integer division
98 // when len < 65535.
99 size_t lz4_extra_buffer(const size_t len)
100 {
101 if (likely(len < 65535))
102 return len + len / 256 + 17;
103 else
104 return len + len / 255 + 16;
105 }
106
108};
109
111{
112 // magic number for LZ4 compression
113 enum
114 {
116 };
117
118 public:
119 CompressLZ4(const Frame::Ptr &frame, const SessionStats::Ptr &stats, const bool asym_arg)
121 asym(asym_arg)
122 {
123 OVPN_LOG_INFO("LZ4 init asym=" << asym_arg);
124 }
125
126 const char *name() const override
127 {
128 return "lz4";
129 }
130
131 void compress(BufferAllocated &buf, const bool hint) override
132 {
133 // skip null packets
134 if (!buf.size())
135 return;
136
137 if (hint && !asym)
138 {
139 if (do_compress(buf))
140 {
141 do_swap(buf, LZ4_COMPRESS);
142 return;
143 }
144 }
145
146 // indicate that we didn't compress
148 }
149
150 void decompress(BufferAllocated &buf) override
151 {
152 // skip null packets
153 if (!buf.size())
154 return;
155
156 const unsigned char c = buf.pop_front();
157 switch (c)
158 {
159 case NO_COMPRESS_SWAP:
160 do_unswap(buf);
161 break;
162 case LZ4_COMPRESS:
163 do_unswap(buf);
164 do_decompress(buf);
165 break;
166 default:
167 error(buf); // unknown op
168 }
169 }
170
171 private:
172 const bool asym;
173};
174
176{
177 public:
178 CompressLZ4v2(const Frame::Ptr &frame, const SessionStats::Ptr &stats, const bool asym_arg)
180 asym(asym_arg)
181 {
182 OVPN_LOG_INFO("LZ4v2 init asym=" << asym_arg);
183 }
184
185 const char *name() const override
186 {
187 return "lz4v2";
188 }
189
190 void compress(BufferAllocated &buf, const bool hint) override
191 {
192 // skip null packets
193 if (!buf.size())
194 return;
195
196 if (hint && !asym)
197 {
198 if (do_compress(buf))
199 {
201 return;
202 }
203 }
204
205 // indicate that we didn't compress
207 }
208
209 void decompress(BufferAllocated &buf) override
210 {
211 // skip null packets
212 if (!buf.size())
213 return;
214
215 const int c = v2_pull(buf);
216 switch (c)
217 {
218 case OVPN_COMPv2_NONE:
219 break;
220 case OVPN_COMPv2_LZ4:
221 do_decompress(buf);
222 break;
223 default:
224 error(buf); // unknown op
225 }
226 }
227
228 private:
229 const bool asym;
230};
231
232} // namespace openvpn
233
234#endif
void swap(BufferAllocatedType< T_ > &other)
Swaps the contents of this BufferAllocatedType object with another BufferAllocatedType object.
Definition buffer.hpp:1799
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:107
size_t lz4_extra_buffer(const size_t len)
Definition lz4.hpp:99
void compress(BufferAllocated &buf, const bool hint) override
Definition lz4.hpp:131
CompressLZ4(const Frame::Ptr &frame, const SessionStats::Ptr &stats, const bool asym_arg)
Definition lz4.hpp:119
const char * name() const override
Definition lz4.hpp:126
const bool asym
Definition lz4.hpp:172
void decompress(BufferAllocated &buf) override
Definition lz4.hpp:150
const char * name() const override
Definition lz4.hpp:185
const bool asym
Definition lz4.hpp:229
void compress(BufferAllocated &buf, const bool hint) override
Definition lz4.hpp:190
CompressLZ4v2(const Frame::Ptr &frame, const SessionStats::Ptr &stats, const bool asym_arg)
Definition lz4.hpp:178
void decompress(BufferAllocated &buf) override
Definition lz4.hpp:209
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:1194
size_t max_size() const
Return the maximum allowable size value in T objects given the current offset (without considering re...
Definition buffer.hpp:1377
size_t capacity() const
Returns the capacity (raw size) of the allocated buffer in T objects.
Definition buffer.hpp:1212
size_t size() const
Returns the size of the buffer in T objects.
Definition buffer.hpp:1242
T * data()
Get a mutable pointer to the start of the array.
Definition buffer.hpp:1450
T pop_front()
Removes and returns the first element from the buffer.
Definition buffer.hpp:1256
void set_size(const size_t size)
After an external method, operating on the array as a mutable unsigned char buffer,...
Definition buffer.hpp:1384
size_t prepare(const unsigned int context, Buffer &buf) const
Definition frame.hpp:266
#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