OpenVPN 3 Core Library
Loading...
Searching...
No Matches
frame.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// Define Frame classes. These classes act as a factory for standard protocol
13// buffers and also try to optimize the buffers for alignment.
14
15#ifndef OPENVPN_FRAME_FRAME_H
16#define OPENVPN_FRAME_FRAME_H
17
20#include <openvpn/common/rc.hpp>
22
23namespace openvpn {
24
25class Frame : public RC<thread_unsafe_refcount>
26{
27 public:
29
30 // Frame context types -- we maintain a Context object for each context type
31 enum
32 {
49
51 };
52
53 OPENVPN_SIMPLE_EXCEPTION(frame_context_index);
54
55 // We manage an array of Context objects, one for each
56 // Frame context above.
57 class Context
58 {
59 public:
61 {
62 headroom_ = 0;
63 payload_ = 0;
64 tailroom_ = 0;
66 align_adjust_ = 0;
67 align_block_ = sizeof(std::size_t);
68 adj_headroom_ = 0;
69 adj_capacity_ = 0;
70 }
71
72 Context(const size_t headroom,
73 const size_t payload,
74 const size_t tailroom,
75 const size_t align_adjust, // length of leading prefix data before the data that needs to be aligned on a size_t boundary
76 const size_t align_block, // size of alignment block, usually sizeof(size_t) but sometimes the cipher block size
77 const BufferFlags buffer_flags) // flags passed to BufferAllocatedRc constructor
78 {
83 align_adjust_ = align_adjust;
84 align_block_ = align_block;
86 }
87
88 void reset_align_adjust(const size_t align_adjust)
89 {
90 align_adjust_ = align_adjust;
91 }
92
93 size_t headroom() const
94 {
95 return adj_headroom_;
96 }
97 size_t payload() const
98 {
99 return payload_;
100 }
101 size_t tailroom() const
102 {
103 return tailroom_;
104 }
105 size_t capacity() const
106 {
107 return adj_capacity_;
108 }
110 {
111 return buffer_flags_;
112 }
113
114 // Calculate a starting offset into a buffer object, dealing with
115 // headroom and alignment issues.
116 size_t prepare(Buffer &buf) const
117 {
118 buf.reset(capacity(), buffer_flags());
120 return payload();
121 }
122
123 // Allocated a new prepared buffer
125 {
126 BufferAllocated buf;
127 prepare(buf);
128 return buf;
129 }
130
131 // Realign a buffer to headroom
132 void realign(Buffer &buf) const
133 {
135 }
136
137 // Return a new BufferAllocatedRc object initialized with the given data.
138 BufferPtr copy(const unsigned char *data, const size_t size) const
139 {
140 const size_t cap = size + headroom() + tailroom();
142 b->init_headroom(actual_headroom(b->c_data_raw()));
143 b->write(data, size);
144 return b;
145 }
146
147 // Return a new BufferAllocated object by value initialized with the given data.
148 BufferAllocated copy_by_value(const unsigned char *data, const size_t size) const
149 {
150 const size_t cap = size + headroom() + tailroom();
153 b.write(data, size);
154 return b;
155 }
156
157 // Return a new BufferAllocatedRc object initialized with
158 // the data in given buffer. buf may be empty or undefined.
159 BufferPtr copy(const BufferPtr &buf) const
160 {
161 const size_t size = buf ? buf->size() : 0;
162 const size_t cap = size + headroom() + tailroom();
164 b->init_headroom(actual_headroom(b->c_data_raw()));
165 if (size)
166 b->write(buf->c_data(), size);
167 return b;
168 }
169
170 // How much payload space left in buffer
171 size_t remaining_payload(const Buffer &buf) const
172 {
173 if (payload() > buf.size())
174 return payload() - buf.size();
175 else
176 return 0;
177 }
178
179 // Used to set the capacity of a group of Context objects
180 // to the highest capacity of any one of the members.
181 void standardize_capacity(const size_t newcap)
182 {
183 if (newcap > adj_capacity_)
184 adj_capacity_ = newcap;
185 }
186
187#ifndef OPENVPN_NO_IO
188 // return a openvpn_io::mutable_buffer object used by
189 // asio read methods.
190 openvpn_io::mutable_buffer mutable_buffer(Buffer &buf) const
191 {
192 return openvpn_io::mutable_buffer(buf.data(), remaining_payload(buf));
193 }
194
195 // clamped version of mutable_buffer
196 openvpn_io::mutable_buffer mutable_buffer_clamp(Buffer &buf) const
197 {
198 return openvpn_io::mutable_buffer(buf.data(), buf_clamp_read(remaining_payload(buf)));
199 }
200#endif
201
202 std::string info() const
203 {
204 std::ostringstream info;
205 info << "head=" << headroom_ << "[" << adj_headroom_ << "] "
206 << "pay=" << payload_ << ' '
207 << "tail=" << tailroom_ << ' '
208 << "cap=" << adj_capacity_ << ' '
209 << "bf=" << buffer_flags_ << ' '
210 << "align_adj=" << align_adjust_ << ' '
211 << "align_block=" << align_block_;
212 return info.str();
213 }
214
215 private:
216 // recalculate derived values when object parameters are modified
218 {
219 // calculate adjusted headroom due to worst-case alignment loss
221
222 // calculate capacity
224 }
225
226 // add a small delta ( < align_block) to headroom so that the point
227 // after the first align_adjust bytes of the buffer starting at base
228 // will be aligned on an align_block boundary
229 size_t actual_headroom(const void *base) const
230 {
231 return headroom_ + (-(size_t(base) + headroom_ + align_adjust_) & (align_block_ - 1));
232 }
233
234 // parameters
235 size_t headroom_;
236 size_t payload_;
237 size_t tailroom_;
241
242 // derived
245 };
246
248 {
249 }
250
251 explicit Frame(const Context &c)
252 {
254 }
255
256 // set the default context
258 {
259 for (int i = 0; i < N_ALIGN_CONTEXTS; ++i)
260 contexts[i] = c;
261 }
262
263 // Calculate a starting offset into a buffer object, dealing with
264 // headroom and alignment issues. context should be one of
265 // the context types above. Returns payload size of buffer.
266 size_t prepare(const unsigned int context, Buffer &buf) const
267 {
268 return (*this)[context].prepare(buf);
269 }
270
271 BufferPtr prepare(const unsigned int context) const
272 {
273 auto buf = BufferAllocatedRc::Create();
274 prepare(context, *buf);
275 return buf;
276 }
277
278 size_t n_contexts() const
279 {
280 return N_ALIGN_CONTEXTS;
281 }
282
283 Context &operator[](const size_t i)
284 {
285 if (i >= N_ALIGN_CONTEXTS)
286 throw frame_context_index();
287 return contexts[i];
288 }
289
290 const Context &operator[](const size_t i) const
291 {
292 if (i >= N_ALIGN_CONTEXTS)
293 throw frame_context_index();
294 return contexts[i];
295 }
296
297 void standardize_capacity(const unsigned int context_mask)
298 {
299 size_t i;
300 size_t max_cap = 0;
301 unsigned int mask = context_mask;
302
303 // find the largest capacity in the group
304 for (i = 0; i < N_ALIGN_CONTEXTS; ++i)
305 {
306 if (mask & 1)
307 {
308 const size_t cap = contexts[i].capacity();
309 if (cap > max_cap)
310 max_cap = cap;
311 }
312 mask >>= 1;
313 }
314
315 // set all members of group to largest capacity found
316 mask = context_mask;
317 for (i = 0; i < N_ALIGN_CONTEXTS; ++i)
318 {
319 if (mask & 1)
320 contexts[i].standardize_capacity(max_cap);
321 mask >>= 1;
322 }
323 }
324
325 private:
327};
328
329} // namespace openvpn
330
331#endif // OPENVPN_FRAME_FRAME_H
void init_headroom(const size_t headroom)
Initializes the headroom (offset) of the buffer.
Definition buffer.hpp:1151
void reset(const size_t min_capacity, const BufferFlags flags)
Reset the buffer with the specified minimum capacity and flags.
Definition buffer.hpp:1609
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
const T * c_data_raw() const
Returns a const pointer to the start of the raw data in the buffer.
Definition buffer.hpp:1206
void write(const T *data, const size_t size)
Write data to the buffer.
Definition buffer.hpp:1563
void realign(size_t headroom)
Realign the buffer with the specified headroom.
Definition buffer.hpp:1551
size_t payload() const
Definition frame.hpp:97
openvpn_io::mutable_buffer mutable_buffer_clamp(Buffer &buf) const
Definition frame.hpp:196
BufferFlags buffer_flags_
Definition frame.hpp:240
std::string info() const
Definition frame.hpp:202
BufferPtr copy(const BufferPtr &buf) const
Definition frame.hpp:159
BufferPtr copy(const unsigned char *data, const size_t size) const
Definition frame.hpp:138
Context(const size_t headroom, const size_t payload, const size_t tailroom, const size_t align_adjust, const size_t align_block, const BufferFlags buffer_flags)
Definition frame.hpp:72
void standardize_capacity(const size_t newcap)
Definition frame.hpp:181
size_t prepare(Buffer &buf) const
Definition frame.hpp:116
size_t tailroom() const
Definition frame.hpp:101
BufferAllocated alloc() const
Definition frame.hpp:124
void reset_align_adjust(const size_t align_adjust)
Definition frame.hpp:88
size_t remaining_payload(const Buffer &buf) const
Definition frame.hpp:171
BufferAllocated copy_by_value(const unsigned char *data, const size_t size) const
Definition frame.hpp:148
BufferFlags buffer_flags() const
Definition frame.hpp:109
size_t actual_headroom(const void *base) const
Definition frame.hpp:229
void realign(Buffer &buf) const
Definition frame.hpp:132
size_t headroom() const
Definition frame.hpp:93
openvpn_io::mutable_buffer mutable_buffer(Buffer &buf) const
Definition frame.hpp:190
size_t capacity() const
Definition frame.hpp:105
Context contexts[N_ALIGN_CONTEXTS]
Definition frame.hpp:326
Frame(const Context &c)
Definition frame.hpp:251
@ WRITE_ACK_STANDALONE
Definition frame.hpp:45
@ WRITE_SSL_CLEARTEXT
Definition frame.hpp:44
@ READ_SSL_CLEARTEXT
Definition frame.hpp:42
@ READ_BIO_MEMQ_DGRAM
Definition frame.hpp:40
@ READ_BIO_MEMQ_STREAM
Definition frame.hpp:41
BufferPtr prepare(const unsigned int context) const
Definition frame.hpp:271
size_t n_contexts() const
Definition frame.hpp:278
Context & operator[](const size_t i)
Definition frame.hpp:283
size_t prepare(const unsigned int context, Buffer &buf) const
Definition frame.hpp:266
OPENVPN_SIMPLE_EXCEPTION(frame_context_index)
void set_default_context(const Context &c)
Definition frame.hpp:257
const Context & operator[](const size_t i) const
Definition frame.hpp:290
void standardize_capacity(const unsigned int context_mask)
Definition frame.hpp:297
RCPtr< Frame > Ptr
Definition frame.hpp:28
The smart pointer class.
Definition rc.hpp:119
Reference count base class for objects tracked by RCPtr. Disallows copying and assignment.
Definition rc.hpp:912
static Ptr Create(ArgsT &&...args)
Creates a new instance of RcEnable with the given arguments.
Definition make_rc.hpp:43
constexpr BufferFlags NO_FLAGS(0u)
no flags set
size_t buf_clamp_read(const size_t size)
Definition bufclamp.hpp:23