mirror of
https://github.com/danog/libtgvoip.git
synced 2024-12-02 09:37:52 +01:00
173 lines
3.7 KiB
C++
173 lines
3.7 KiB
C++
//
|
|
// 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 "controller/net/CongestionControl.h"
|
|
#include "VoIPController.h"
|
|
#include "tools/logging.h"
|
|
#include "VoIPServerConfig.h"
|
|
#include "controller/PrivateDefines.h"
|
|
#include <math.h>
|
|
#include <assert.h>
|
|
|
|
using namespace tgvoip;
|
|
|
|
CongestionControl::CongestionControl()
|
|
{
|
|
memset(inflightPackets, 0, sizeof(inflightPackets));
|
|
tmpRtt = 0;
|
|
tmpRttCount = 0;
|
|
lastSentSeq = 0;
|
|
lastActionTime = 0;
|
|
lastActionRtt = 0;
|
|
stateTransitionTime = 0;
|
|
inflightDataSize = 0;
|
|
lossCount = 0;
|
|
cwnd = (size_t)ServerConfig::GetSharedInstance()->GetInt("audio_congestion_window", 1024);
|
|
}
|
|
|
|
CongestionControl::~CongestionControl()
|
|
{
|
|
}
|
|
|
|
size_t CongestionControl::GetAcknowledgedDataSize()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
double CongestionControl::GetAverageRTT()
|
|
{
|
|
return rttHistory.NonZeroAverage();
|
|
}
|
|
|
|
size_t CongestionControl::GetInflightDataSize()
|
|
{
|
|
return inflightHistory.Average();
|
|
}
|
|
|
|
size_t CongestionControl::GetCongestionWindow()
|
|
{
|
|
return cwnd;
|
|
}
|
|
|
|
double CongestionControl::GetMinimumRTT()
|
|
{
|
|
return rttHistory.Min();
|
|
}
|
|
|
|
void CongestionControl::PacketAcknowledged(uint32_t seq)
|
|
{
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
if (inflightPackets[i].seq == seq && inflightPackets[i].sendTime > 0)
|
|
{
|
|
tmpRtt += (VoIPController::GetCurrentTime() - inflightPackets[i].sendTime);
|
|
tmpRttCount++;
|
|
inflightPackets[i].sendTime = 0;
|
|
inflightDataSize -= inflightPackets[i].size;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CongestionControl::PacketSent(uint32_t seq, size_t size)
|
|
{
|
|
if (!seqgt(seq, lastSentSeq) || seq == lastSentSeq)
|
|
{
|
|
LOGW("Duplicate outgoing seq %u", seq);
|
|
return;
|
|
}
|
|
lastSentSeq = seq;
|
|
double smallestSendTime = INFINITY;
|
|
tgvoip_congestionctl_packet_t *slot = NULL;
|
|
int i;
|
|
for (i = 0; i < 100; i++)
|
|
{
|
|
if (inflightPackets[i].sendTime == 0)
|
|
{
|
|
slot = &inflightPackets[i];
|
|
break;
|
|
}
|
|
if (smallestSendTime > inflightPackets[i].sendTime)
|
|
{
|
|
slot = &inflightPackets[i];
|
|
smallestSendTime = slot->sendTime;
|
|
}
|
|
}
|
|
assert(slot != NULL);
|
|
if (slot->sendTime > 0)
|
|
{
|
|
inflightDataSize -= slot->size;
|
|
lossCount++;
|
|
LOGD("Packet with seq %u was not acknowledged", slot->seq);
|
|
}
|
|
slot->seq = seq;
|
|
slot->size = size;
|
|
slot->sendTime = VoIPController::GetCurrentTime();
|
|
inflightDataSize += size;
|
|
}
|
|
|
|
void CongestionControl::PacketLost(uint32_t seq)
|
|
{
|
|
for (int i = 0; i < 100; i++)
|
|
{
|
|
if (inflightPackets[i].seq == seq && inflightPackets[i].sendTime > 0)
|
|
{
|
|
inflightPackets[i].sendTime = 0;
|
|
inflightDataSize -= inflightPackets[i].size;
|
|
lossCount++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CongestionControl::Tick()
|
|
{
|
|
tickCount++;
|
|
if (tmpRttCount > 0)
|
|
{
|
|
rttHistory.Add(tmpRtt / tmpRttCount);
|
|
tmpRtt = 0;
|
|
tmpRttCount = 0;
|
|
}
|
|
int i;
|
|
for (i = 0; i < 100; i++)
|
|
{
|
|
if (inflightPackets[i].sendTime != 0 && VoIPController::GetCurrentTime() - inflightPackets[i].sendTime > 2)
|
|
{
|
|
inflightPackets[i].sendTime = 0;
|
|
inflightDataSize -= inflightPackets[i].size;
|
|
lossCount++;
|
|
LOGD("Packet with seq %u was not acknowledged", inflightPackets[i].seq);
|
|
}
|
|
}
|
|
inflightHistory.Add(inflightDataSize);
|
|
}
|
|
|
|
int CongestionControl::GetBandwidthControlAction()
|
|
{
|
|
if (VoIPController::GetCurrentTime() - lastActionTime < 1)
|
|
return TGVOIP_CONCTL_ACT_NONE;
|
|
size_t inflightAvg = GetInflightDataSize();
|
|
size_t max = cwnd + cwnd / 10;
|
|
size_t min = cwnd - cwnd / 10;
|
|
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;
|
|
}
|
|
|
|
uint32_t CongestionControl::GetSendLossCount()
|
|
{
|
|
return lossCount;
|
|
}
|