TeaSpeakLibrary/src/protocol/AcknowledgeManager.cpp

150 lines
5.2 KiB
C++
Raw Normal View History

2019-06-26 22:11:22 +02:00
#include "AcknowledgeManager.h"
2020-02-18 11:53:32 +01:00
#include <cmath>
2019-06-26 22:11:22 +02:00
#include <misc/endianness.h>
using namespace ts;
using namespace ts::connection;
using namespace ts::protocol;
using namespace std;
using namespace std::chrono;
2020-02-18 11:53:32 +01:00
AcknowledgeManager::AcknowledgeManager() = default;
2019-06-26 22:11:22 +02:00
AcknowledgeManager::~AcknowledgeManager() {
2020-02-18 11:53:32 +01:00
this->reset();
2019-06-26 22:11:22 +02:00
}
void AcknowledgeManager::reset() {
2020-01-24 02:49:59 +01:00
{
2020-02-18 11:53:32 +01:00
std::unique_lock lock{this->entry_lock};
auto pending_entries = std::move(this->entries);
lock.unlock();
/* save because entries are not accessable anymore */
for(const auto& entry : pending_entries)
2020-01-24 02:49:59 +01:00
if(entry->acknowledge_listener)
entry->acknowledge_listener->executionFailed("reset");
}
2019-06-26 22:11:22 +02:00
}
size_t AcknowledgeManager::awaiting_acknowledge() {
2020-02-18 11:53:32 +01:00
std::lock_guard lock(this->entry_lock);
2020-01-24 02:49:59 +01:00
return this->entries.size();
2019-06-26 22:11:22 +02:00
}
void AcknowledgeManager::process_packet(ts::protocol::BasicPacket &packet) {
2020-01-24 02:49:59 +01:00
if(!packet.type().requireAcknowledge()) return;
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
auto entry = make_shared<Entry>();
entry->acknowledge_listener = std::move(packet.getListener());
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
entry->buffer = packet.buffer();
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
entry->resend_count = 0;
entry->first_send = system_clock::now();
entry->next_resend = entry->first_send + std::chrono::milliseconds{(int64_t) ceil(this->rto)};
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
entry->packet_type = packet.type().type();
entry->packet_id = packet.packetId();
entry->generation_id = packet.generationId();
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
entry->acknowledged = false;
entry->send_count = 1;
{
2020-02-18 11:53:32 +01:00
std::lock_guard lock(this->entry_lock);
2020-01-24 02:49:59 +01:00
this->entries.push_front(std::move(entry));
}
2019-06-26 22:11:22 +02:00
}
bool AcknowledgeManager::process_acknowledge(uint8_t packet_type, uint16_t target_id, std::string& error) {
2020-02-18 11:53:32 +01:00
PacketType target_type{packet_type == protocol::ACK_LOW ? PacketType::COMMAND_LOW : PacketType::COMMAND};
2020-01-24 02:49:59 +01:00
std::shared_ptr<Entry> entry;
2020-02-18 11:53:32 +01:00
std::unique_ptr<threads::Future<bool>> ack_listener;
2020-01-24 02:49:59 +01:00
{
2020-02-18 11:53:32 +01:00
std::lock_guard lock{this->entry_lock};
2020-01-24 02:49:59 +01:00
for(auto it = this->entries.begin(); it != this->entries.end(); it++) {
if((*it)->packet_type == target_type && (*it)->packet_id == target_id) {
entry = *it;
2020-02-18 11:53:32 +01:00
ack_listener = std::move(entry->acknowledge_listener); /* move it out so nobody else could call it as well */
2020-01-24 02:49:59 +01:00
entry->send_count--;
if(entry->send_count == 0) {
2020-01-24 02:49:59 +01:00
this->entries.erase(it);
if(entry->resend_count == 0) {
auto difference = std::chrono::system_clock::now() - entry->first_send;
this->update_rto(std::chrono::duration_cast<std::chrono::milliseconds>(difference).count());
}
}
2020-01-24 02:49:59 +01:00
break;
}
}
}
if(!entry) {
error = "Missing packet id (" + to_string(target_id) + ")";
return false;
}
entry->acknowledged = true;
2020-02-18 11:53:32 +01:00
if(ack_listener) ack_listener->executionSucceed(true);
2020-01-24 02:49:59 +01:00
return true;
2019-06-26 22:11:22 +02:00
}
ssize_t AcknowledgeManager::execute_resend(const system_clock::time_point& now , std::chrono::system_clock::time_point &next_resend,std::deque<std::shared_ptr<Entry>>& buffers, string& error) {
2020-02-18 11:53:32 +01:00
size_t resend_count{0};
2020-01-24 02:49:59 +01:00
2020-02-18 11:53:32 +01:00
vector<shared_ptr<Entry>> need_resend;
2020-01-24 02:49:59 +01:00
{
2020-02-18 11:53:32 +01:00
bool cleanup{false};
std::lock_guard lock{this->entry_lock};
2020-02-18 12:11:02 +01:00
need_resend.reserve(this->entries.size());
2020-01-24 02:49:59 +01:00
for (auto &entry : this->entries) {
if(entry->acknowledged) {
if(entry->next_resend + std::chrono::milliseconds{(int64_t) ceil(this->rto * 4)} <= now) { // Some resends are lost. So we just drop it after time
2020-02-18 11:53:32 +01:00
entry.reset();
cleanup = true;
2020-01-24 02:49:59 +01:00
}
} else {
2020-02-18 11:53:32 +01:00
if(entry->next_resend <= now) {
entry->next_resend = now + std::chrono::milliseconds{(int64_t) min(ceil(this->rto), 1500.f)};
2020-02-18 11:53:32 +01:00
need_resend.push_back(entry);
}
2020-01-24 02:49:59 +01:00
if(next_resend > entry->next_resend)
next_resend = entry->next_resend;
}
}
2020-02-18 11:53:32 +01:00
if(cleanup) {
this->entries.erase(std::remove_if(this->entries.begin(), this->entries.end(),
[](const auto& entry) { return !entry; }), this->entries.end());
2020-01-24 02:49:59 +01:00
}
}
for(const auto& packet : need_resend) {
if(packet->resend_count > 15 && packet->first_send + seconds(15) < now) { //FIXME configurable
error = "Failed to receive acknowledge for packet " + to_string(packet->packet_id) + " of type " + PacketTypeInfo::fromid(packet->packet_type).name();
return -1;
}
resend_count++;
packet->resend_count++;
packet->send_count++;
buffers.push_back(packet);
2020-01-24 02:49:59 +01:00
}
return resend_count;
}
/* we're not taking the clock granularity into account because its nearly 1ms and it would only add more branches */
void AcknowledgeManager::update_rto(size_t r) {
if(srtt == -1) {
this->srtt = r;
this->rttvar = r / 2.f;
this->rto = srtt + 4 * this->rttvar;
} else {
this->rttvar = (1.f - alpha) * this->rttvar + beta * abs(this->srtt - r);
this->srtt = (1.f - alpha) * srtt + alpha * r;
this->rto = std::min(200.f, this->srtt + 4 * this->rttvar);
}
2019-06-26 22:11:22 +02:00
}