OpenVPN 3 Core Library
Loading...
Searching...
No Matches
msgwin.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_COMMON_MSGWIN_H
13#define OPENVPN_COMMON_MSGWIN_H
14
15#include <deque>
16
19
20// Fundamental, lowest-level object of OpenVPN protocol reliability layer
21
22namespace openvpn {
23
24// MessageWindow --
25// On receiving side: used to order packets which may be received out-of-order
26// On sending side: used to buffer unacknowledged packets
27// M : message class, must define default constructor, defined(), and erase() methods
28// id_t : sequence number object, usually unsigned int
29template <typename M, typename id_t>
31{
32 public:
33 OPENVPN_SIMPLE_EXCEPTION(message_window_ref_by_id);
34 OPENVPN_SIMPLE_EXCEPTION(message_window_rm_head);
35
37 : head_id_(0), span_(0)
38 {
39 }
40
41 MessageWindow(const id_t starting_head_id, const id_t span)
42 : head_id_(starting_head_id), span_(span)
43 {
44 }
45
46 void init(const id_t starting_head_id, const id_t span)
47 {
48 head_id_ = starting_head_id;
49 span_ = span;
50 q_.clear();
51 }
52
53 // Return true if id is within current window
54 bool in_window(const id_t id) const
55 {
56 return id >= head_id_ && id < head_id_ + span_;
57 }
58
59 // Return true if id is before current window
60 bool pre_window(const id_t id) const
61 {
62 return id < head_id_;
63 }
64
65 // Return a reference to M object at id, throw exception
66 // if id is not in current window
67 M &ref_by_id(const id_t id)
68 {
69 if (in_window(id))
70 {
71 grow(id);
72 return q_[id - head_id_];
73 }
74 throw message_window_ref_by_id();
75 }
76
77 // Remove the M object at id, is a no-op if
78 // id not in window. Do a purge() as a last
79 // step to advance the head_id_ if it's now
80 // pointing at undefined M objects.
81 void rm_by_id(const id_t id)
82 {
83 if (in_window(id))
84 {
85 grow(id);
86 M &m = q_[id - head_id_];
87 m.erase();
88 }
89 purge();
90 }
91
92 // Return true if an object at head of queue is defined
93 bool head_defined() const
94 {
95 return (!q_.empty() && q_.front().defined());
96 }
97
98 // Return the id that the object at the head of the queue
99 // would have (even if it isn't defined yet).
100 id_t head_id() const
101 {
102 return head_id_;
103 }
104
105 // Return the id of one past the end of the window
106 id_t tail_id() const
107 {
108 return head_id_ + span_;
109 }
110
111 // Return the window size
112 id_t span() const
113 {
114 return span_;
115 }
116
117 // Return a reference to the object at the front of the queue
119 {
120 return q_.front();
121 }
122
123 // Remove the object at head of queue, throw an exception if undefined
124 void rm_head()
125 {
126 if (head_defined())
128 else
129 throw message_window_rm_head();
130 }
131
132 // Remove the object at head of queue without error checking (other than
133 // that provided by std::deque object). Don't call this method unless
134 // head_defined() returns true.
136 {
137 q_.front().erase();
138 q_.pop_front();
139 ++head_id_;
140 }
141
142 private:
143 // Expand the queue if necessary so that id maps
144 // to an object in the queue
145 void grow(const id_t id)
146 {
147 const size_t needed_index = id - head_id_;
148 while (q_.size() <= needed_index)
149 q_.push_back(M());
150 }
151
152 // Purge all undefined objects at the head of
153 // the queue, advancing the head_id_
154 void purge()
155 {
156 while (!q_.empty() && q_.front().erased())
157 {
158 q_.pop_front();
159 ++head_id_;
160 }
161 }
162
163 id_t head_id_; // id of msgs[0]
164 id_t span_;
165 std::deque<M> q_;
166};
167
168} // namespace openvpn
169
170#endif // OPENVPN_COMMON_MSGWIN_H
bool in_window(const id_t id) const
Definition msgwin.hpp:54
OPENVPN_SIMPLE_EXCEPTION(message_window_rm_head)
bool pre_window(const id_t id) const
Definition msgwin.hpp:60
void rm_by_id(const id_t id)
Definition msgwin.hpp:81
std::deque< M > q_
Definition msgwin.hpp:165
M & ref_by_id(const id_t id)
Definition msgwin.hpp:67
MessageWindow(const id_t starting_head_id, const id_t span)
Definition msgwin.hpp:41
id_t span() const
Definition msgwin.hpp:112
id_t head_id() const
Definition msgwin.hpp:100
bool head_defined() const
Definition msgwin.hpp:93
void grow(const id_t id)
Definition msgwin.hpp:145
void init(const id_t starting_head_id, const id_t span)
Definition msgwin.hpp:46
OPENVPN_SIMPLE_EXCEPTION(message_window_ref_by_id)
id_t tail_id() const
Definition msgwin.hpp:106