1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2012- OpenVPN Inc.
//
// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
//
// Sender side of reliability layer
#ifndef OPENVPN_RELIABLE_RELSEND_H
#define OPENVPN_RELIABLE_RELSEND_H
#include <openvpn/common/size.hpp>
#include <openvpn/common/exception.hpp>
#include <openvpn/common/msgwin.hpp>
#include <openvpn/time/time.hpp>
#include <openvpn/reliable/relcommon.hpp>
namespace openvpn {
template <typename PACKET>
class ReliableSendTemplate
{
public:
typedef reliable::id_t id_t;
class Message : public ReliableMessageBase<PACKET>
{
friend class ReliableSendTemplate;
using ReliableMessageBase<PACKET>::defined;
public:
bool ready_retransmit(const Time &now) const
{
return defined() && now >= retransmit_at_;
}
Time::Duration until_retransmit(const Time &now) const
{
Time::Duration ret;
if (now < retransmit_at_)
ret = retransmit_at_ - now;
return ret;
}
void reset_retransmit(const Time &now, const Time::Duration &tls_timeout)
{
retransmit_at_ = now + tls_timeout;
}
private:
Time retransmit_at_;
};
ReliableSendTemplate()
: next(0)
{
}
ReliableSendTemplate(const id_t span, id_t start_at = 0)
{
init(span, start_at);
}
void init(const id_t span, id_t start_at = 0)
{
next = start_at;
window_.init(next, span);
}
// Return the id that the object at the head of the queue
// would have (even if it isn't defined yet).
id_t head_id() const
{
return window_.head_id();
}
// Return the ID of one past the end of the window
id_t tail_id() const
{
return window_.tail_id();
}
// Return the window size
id_t span() const
{
return window_.span();
}
// Return a reference to M object at id, throw exception
// if id is not in current window
Message &ref_by_id(const id_t id)
{
return window_.ref_by_id(id);
}
// Return the shortest duration for any pending retransmissions
Time::Duration until_retransmit(const Time &now)
{
Time::Duration ret = Time::Duration::infinite();
for (id_t i = head_id(); i < tail_id(); ++i)
{
const Message &msg = ref_by_id(i);
if (msg.defined())
{
Time::Duration ut = msg.until_retransmit(now);
if (ut < ret)
ret = ut;
}
}
return ret;
}
// Return number of unacknowleged packets in send queue
unsigned int n_unacked()
{
unsigned int ret = 0;
for (id_t i = head_id(); i < tail_id(); ++i)
{
if (ref_by_id(i).defined())
++ret;
}
return ret;
}
// Return a fresh Message object that can be used to
// construct the next packet in the sequence. Don't call
// unless ready() returns true.
Message &send(const Time &now, const Time::Duration &tls_timeout)
{
Message &msg = window_.ref_by_id(next);
msg.id_ = next++;
msg.reset_retransmit(now, tls_timeout);
return msg;
}
// Return true if send queue is ready to receive another packet
bool ready() const
{
return window_.in_window(next);
}
// Remove a message from send queue that has been acknowledged
void ack(const id_t id)
{
window_.rm_by_id(id);
}
private:
id_t next;
MessageWindow<Message, id_t> window_;
};
} // namespace openvpn
#endif // OPENVPN_RELIABLE_RELSEND_H
|