OpenVPN 3 Core Library
Loading...
Searching...
No Matches
relack.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// Handle ACK tracking for reliability layer
13
14#pragma once
15
16
17#include <deque>
18#include <algorithm>
19#include <limits>
20
25
26namespace openvpn {
27
29{
30 public:
31 static constexpr size_t maximum_acks_ack_v1 = 8;
32 static constexpr size_t maximum_acks_control_v1 = 4;
34
35 explicit ReliableAck() = default;
36 size_t size() const;
37 bool empty() const;
38 bool acks_ready() const;
39 void push_back(id_t value)
40 {
41 data.push_back(value);
42 }
43 id_t front() const
44 {
45 return data.front();
46 }
47 void pop_front()
48 {
49 data.pop_front();
50 }
51
52 // Called to read incoming ACK IDs from buf and mark them as ACKed in rel_send.
53 // If live is false, read the ACK IDs, but don't modify rel_send.
54 // Return the number of ACK IDs read.
55 template <typename REL_SEND>
56 static size_t ack(REL_SEND &rel_send, Buffer &buf, const bool live)
57 {
58 const size_t len = buf.pop_front();
59 for (size_t i = 0; i < len; ++i)
60 {
61 const id_t id = read_id(buf);
62 if (live)
63 rel_send.ack(id);
64 }
65 return len;
66 }
67
68 static size_t ack_skip(Buffer &buf)
69 {
70 const size_t len = buf.pop_front();
71 for (size_t i = 0; i < len; ++i)
72 read_id(buf);
73 return len;
74 }
75
76 // copy ACKs from buffer to self
77 void read(Buffer &buf)
78 {
79 const size_t len = buf.pop_front();
80 for (size_t i = 0; i < len; ++i)
81 {
82 const id_t id = read_id(buf);
83 data.push_back(id);
84 }
85 }
86
93 void prepend(Buffer &buf, bool ackv1)
94 {
95 size_t max_acks = ackv1 ? maximum_acks_ack_v1 : maximum_acks_control_v1;
96
97 size_t acks_added = 0;
98
99 while (acks_added < max_acks && data.size() > 0)
100 {
101 auto ack = data.front();
102 data.pop_front();
103
104 prepend_id(buf, ack);
105 acks_added++;
107 }
108
109 /* the already pushed acks are in front of the re_acks list, so we
110 * skip over them */
111 while (acks_added < re_acks.size() && acks_added < max_acks)
112 {
113 prepend_id(buf, re_acks[acks_added]);
114 acks_added++;
115 }
116 buf.push_front((unsigned char)acks_added);
117 }
118
119 static void prepend_id(Buffer &buf, const id_t id)
120 {
121 const id_t net_id = htonl(id);
122 buf.prepend((unsigned char *)&net_id, sizeof(net_id));
123 }
124
125 static id_t read_id(Buffer &buf)
126 {
127 id_t net_id;
128 buf.read((unsigned char *)&net_id, sizeof(net_id));
129 return ntohl(net_id);
130 }
131
132 size_t resend_size();
133
134 private:
136
137 std::deque<id_t> data;
138 std::deque<id_t> re_acks;
139};
140
144inline size_t ReliableAck::size() const
145{
146 return data.size();
147}
148
156inline bool ReliableAck::empty() const
157{
158 return data.empty();
159}
160
166inline bool ReliableAck::acks_ready() const
167{
168 return !data.empty() || !re_acks.empty();
169}
170
172{
173 /* Check if the element is already in the array to avoid duplicates */
174 for (auto it = re_acks.begin(); it != re_acks.end(); it++)
175 {
176 if (*it == ack)
177 {
178 re_acks.erase(it);
179 break;
180 }
181 }
182
183 re_acks.push_front(ack);
184 if (re_acks.size() > maximum_acks_ack_v1)
185 {
186 re_acks.pop_back();
187 }
188}
189
191{
192 return re_acks.size();
193}
194
195} // namespace openvpn
void prepend(const T *data, const size_t size)
Prepend data to the buffer.
Definition buffer.hpp:1558
T pop_front()
Removes and returns the first element from the buffer.
Definition buffer.hpp:1239
void push_front(const T &value)
Append a T object to the array, with possible resize.
Definition buffer.hpp:1473
void read(NCT *data, const size_t size)
Read data from the buffer into the specified memory location.
Definition buffer.hpp:1314
static void prepend_id(Buffer &buf, const id_t id)
Definition relack.hpp:119
bool acks_ready() const
Definition relack.hpp:166
void push_back(id_t value)
Definition relack.hpp:39
std::deque< id_t > data
Definition relack.hpp:137
void prepend(Buffer &buf, bool ackv1)
Definition relack.hpp:93
bool empty() const
Definition relack.hpp:156
static id_t read_id(Buffer &buf)
Definition relack.hpp:125
static constexpr size_t maximum_acks_ack_v1
Definition relack.hpp:31
void add_ack_to_reack(id_t ack)
Definition relack.hpp:171
id_t front() const
Definition relack.hpp:43
reliable::id_t id_t
Definition relack.hpp:33
static constexpr size_t maximum_acks_control_v1
Definition relack.hpp:32
static size_t ack_skip(Buffer &buf)
Definition relack.hpp:68
std::deque< id_t > re_acks
Definition relack.hpp:138
static size_t ack(REL_SEND &rel_send, Buffer &buf, const bool live)
Definition relack.hpp:56
void read(Buffer &buf)
Definition relack.hpp:77
size_t size() const
Definition relack.hpp:144
std::uint32_t id_t
Definition relcommon.hpp:22
Support deferred server-side state creation when client connects.
Definition ovpncli.cpp:95