1
0
mirror of https://github.com/danog/libtgvoip.git synced 2024-12-12 09:09:38 +01:00
libtgvoip/controller/net/CongestionControl.cpp

171 lines
4.5 KiB
C++
Raw Normal View History

2020-01-22 12:43:51 +01:00
//
// libtgvoip is free and unencumbered public domain software.
// For more information, see http://unlicense.org or the UNLICENSE file
// you should have received with this source code distribution.
//
#include "CongestionControl.h"
2020-03-22 21:25:02 +01:00
#include "../PrivateDefines.h"
2020-03-24 12:15:04 +01:00
#include "../protocol/packets/PacketStructs.h"
2020-01-22 12:43:51 +01:00
#include "VoIPController.h"
#include "VoIPServerConfig.h"
2020-03-22 21:25:02 +01:00
#include "tools/logging.h"
2020-01-22 12:43:51 +01:00
#include <assert.h>
2020-03-22 21:25:02 +01:00
#include <math.h>
2020-01-22 12:43:51 +01:00
using namespace tgvoip;
2020-03-24 12:15:04 +01:00
CongestionControlPacket::CongestionControlPacket(uint32_t _seq, uint8_t _streamId) : seq(_seq), streamId(_streamId){};
CongestionControlPacket::CongestionControlPacket(const Packet &pkt) : seq(pkt.seq), streamId(pkt.streamId){};
2020-03-13 21:12:58 +01:00
CongestionControl::CongestionControl() : cwnd(static_cast<size_t>(ServerConfig::GetSharedInstance()->GetInt("audio_congestion_window", 1024))),
2020-03-22 21:25:02 +01:00
max(cwnd * 1.1),
min(cwnd * 0.9)
2020-01-22 12:43:51 +01:00
{
}
CongestionControl::~CongestionControl()
{
}
size_t CongestionControl::GetAcknowledgedDataSize()
{
2020-03-22 21:25:02 +01:00
return 0;
2020-01-22 12:43:51 +01:00
}
double CongestionControl::GetAverageRTT()
{
2020-03-22 21:25:02 +01:00
return rttHistory.NonZeroAverage();
2020-01-22 12:43:51 +01:00
}
size_t CongestionControl::GetInflightDataSize()
{
2020-03-22 21:25:02 +01:00
return inflightHistory.Average();
2020-01-22 12:43:51 +01:00
}
size_t CongestionControl::GetCongestionWindow()
{
2020-03-22 21:25:02 +01:00
return cwnd;
2020-01-22 12:43:51 +01:00
}
double CongestionControl::GetMinimumRTT()
{
2020-03-22 21:25:02 +01:00
return rttHistory.Min();
2020-01-22 12:43:51 +01:00
}
2020-03-24 12:15:04 +01:00
void CongestionControl::PacketSent(const CongestionControlPacket &pkt, size_t size)
2020-01-22 12:43:51 +01:00
{
2020-03-24 12:15:04 +01:00
if (lastSentSeq.find(pkt.streamId) == lastSentSeq.end())
2020-03-22 21:25:02 +01:00
{
2020-03-24 12:15:04 +01:00
lastSentSeq[pkt.streamId] = 0;
2020-03-22 21:25:02 +01:00
}
2020-03-24 12:15:04 +01:00
if (!seqgt(pkt.seq, lastSentSeq[pkt.streamId]) || pkt.seq == lastSentSeq[pkt.streamId])
2020-03-22 21:25:02 +01:00
{
2020-03-24 12:15:04 +01:00
LOGW("Duplicate outgoing seq %u", pkt.seq);
2020-03-22 21:25:02 +01:00
return;
}
2020-03-24 12:15:04 +01:00
lastSentSeq[pkt.streamId] = pkt.seq;
2020-03-22 21:25:02 +01:00
double smallestSendTime = INFINITY;
tgvoip_congestionctl_packet_t *slot = NULL;
for (auto &packet : inflightPackets)
{
if (packet.sendTime == 0)
{
slot = &packet;
break;
}
if (smallestSendTime > packet.sendTime)
{
slot = &packet;
smallestSendTime = slot->sendTime;
}
}
assert(slot != NULL);
if (slot->sendTime > 0)
{
inflightDataSize -= slot->size;
lossCount++;
LOGD("Packet with seq %u, streamId=%hhu was not acknowledged", slot->seq, slot->streamId);
}
2020-03-24 12:15:04 +01:00
slot->seq = pkt.seq;
2020-03-22 21:25:02 +01:00
slot->size = size;
2020-03-24 12:15:04 +01:00
slot->streamId = pkt.streamId;
2020-03-22 21:25:02 +01:00
slot->sendTime = VoIPController::GetCurrentTime();
inflightDataSize += size;
2020-01-22 12:43:51 +01:00
}
2020-03-24 12:15:04 +01:00
void CongestionControl::PacketAcknowledged(const CongestionControlPacket &pkt)
2020-03-13 21:12:58 +01:00
{
2020-03-22 21:25:02 +01:00
for (auto &packet : inflightPackets)
{
2020-03-24 12:15:04 +01:00
if (packet.seq == pkt.seq && packet.streamId == pkt.streamId && packet.sendTime > 0)
2020-03-22 21:25:02 +01:00
{
tmpRtt += (VoIPController::GetCurrentTime() - packet.sendTime);
tmpRttCount++;
packet.sendTime = 0;
inflightDataSize -= packet.size;
break;
}
}
2020-03-13 21:12:58 +01:00
}
2020-03-24 12:15:04 +01:00
void CongestionControl::PacketLost(const CongestionControlPacket &pkt)
2020-01-22 12:43:51 +01:00
{
2020-03-22 21:25:02 +01:00
for (auto &packet : inflightPackets)
{
2020-03-24 12:15:04 +01:00
if (packet.seq == pkt.seq && packet.streamId == pkt.streamId && packet.sendTime > 0)
2020-03-22 21:25:02 +01:00
{
packet.sendTime = 0;
inflightDataSize -= packet.size;
lossCount++;
break;
}
}
2020-01-22 12:43:51 +01:00
}
void CongestionControl::Tick()
{
2020-03-22 21:25:02 +01:00
tickCount++;
if (tmpRttCount > 0)
{
rttHistory.Add(tmpRtt / tmpRttCount);
tmpRtt = 0;
tmpRttCount = 0;
}
for (auto &packet : inflightPackets)
{
if (packet.sendTime && VoIPController::GetCurrentTime() - packet.sendTime > TGVOIP_CONCTL_LOST_AFTER)
{
packet.sendTime = 0;
inflightDataSize -= packet.size;
lossCount++;
LOGD("Packet with seq %u was not acknowledged", packet.seq);
}
}
inflightHistory.Add(inflightDataSize);
2020-01-22 12:43:51 +01:00
}
int CongestionControl::GetBandwidthControlAction()
{
2020-03-22 21:25:02 +01:00
if (VoIPController::GetCurrentTime() - lastActionTime < 1)
return TGVOIP_CONCTL_ACT_NONE;
size_t inflightAvg = GetInflightDataSize();
if (inflightAvg < min)
{
lastActionTime = VoIPController::GetCurrentTime();
return TGVOIP_CONCTL_ACT_INCREASE;
}
if (inflightAvg > max)
{
lastActionTime = VoIPController::GetCurrentTime();
return TGVOIP_CONCTL_ACT_DECREASE;
}
return TGVOIP_CONCTL_ACT_NONE;
2020-01-22 12:43:51 +01:00
}
uint32_t CongestionControl::GetSendLossCount()
{
2020-03-22 21:25:02 +01:00
return lossCount;
2020-01-22 12:43:51 +01:00
}