mirror of
https://github.com/JulianGro/overte.git
synced 2025-08-12 13:34:51 +02:00
Basic congestion control using TCP-esque strategy.
This commit is contained in:
parent
8999fcef17
commit
705445ce62
3 changed files with 60 additions and 10 deletions
|
@ -23,6 +23,9 @@ const int MAX_DATAGRAM_SIZE = MAX_PACKET_SIZE;
|
||||||
|
|
||||||
const int DEFAULT_MAX_PACKET_SIZE = 3000;
|
const int DEFAULT_MAX_PACKET_SIZE = 3000;
|
||||||
|
|
||||||
|
// the default slow-start threshold, which will be lowered quickly when we first encounter packet loss
|
||||||
|
const float DEFAULT_SLOW_START_THRESHOLD = 1000.0f;
|
||||||
|
|
||||||
DatagramSequencer::DatagramSequencer(const QByteArray& datagramHeader, QObject* parent) :
|
DatagramSequencer::DatagramSequencer(const QByteArray& datagramHeader, QObject* parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
_outgoingPacketStream(&_outgoingPacketData, QIODevice::WriteOnly),
|
_outgoingPacketStream(&_outgoingPacketData, QIODevice::WriteOnly),
|
||||||
|
@ -37,7 +40,12 @@ DatagramSequencer::DatagramSequencer(const QByteArray& datagramHeader, QObject*
|
||||||
_incomingPacketStream(&_incomingPacketData, QIODevice::ReadOnly),
|
_incomingPacketStream(&_incomingPacketData, QIODevice::ReadOnly),
|
||||||
_inputStream(_incomingPacketStream),
|
_inputStream(_incomingPacketStream),
|
||||||
_receivedHighPriorityMessages(0),
|
_receivedHighPriorityMessages(0),
|
||||||
_maxPacketSize(DEFAULT_MAX_PACKET_SIZE) {
|
_maxPacketSize(DEFAULT_MAX_PACKET_SIZE),
|
||||||
|
_packetsPerGroup(1.0f),
|
||||||
|
_packetsToWrite(0.0f),
|
||||||
|
_slowStartThreshold(DEFAULT_SLOW_START_THRESHOLD),
|
||||||
|
_packetRateIncreasePacketNumber(0),
|
||||||
|
_packetRateDecreasePacketNumber(0) {
|
||||||
|
|
||||||
_outgoingPacketStream.setByteOrder(QDataStream::LittleEndian);
|
_outgoingPacketStream.setByteOrder(QDataStream::LittleEndian);
|
||||||
_incomingDatagramStream.setByteOrder(QDataStream::LittleEndian);
|
_incomingDatagramStream.setByteOrder(QDataStream::LittleEndian);
|
||||||
|
@ -71,6 +79,14 @@ ReliableChannel* DatagramSequencer::getReliableInputChannel(int index) {
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DatagramSequencer::startPacketGroup() {
|
||||||
|
// increment our packet counter and subtract/return the integer portion
|
||||||
|
_packetsToWrite += _packetsPerGroup;
|
||||||
|
int wholePackets = (int)_packetsToWrite;
|
||||||
|
_packetsToWrite -= wholePackets;
|
||||||
|
return wholePackets;
|
||||||
|
}
|
||||||
|
|
||||||
Bitstream& DatagramSequencer::startPacket() {
|
Bitstream& DatagramSequencer::startPacket() {
|
||||||
// start with the list of acknowledgements
|
// start with the list of acknowledgements
|
||||||
_outgoingPacketStream << (quint32)_receiveRecords.size();
|
_outgoingPacketStream << (quint32)_receiveRecords.size();
|
||||||
|
@ -256,6 +272,14 @@ void DatagramSequencer::sendRecordAcknowledged(const SendRecord& record) {
|
||||||
foreach (const ChannelSpan& span, record.spans) {
|
foreach (const ChannelSpan& span, record.spans) {
|
||||||
getReliableOutputChannel(span.channel)->spanAcknowledged(span);
|
getReliableOutputChannel(span.channel)->spanAcknowledged(span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// increase the packet rate with every ack until we pass the slow start threshold; then, every round trip
|
||||||
|
if (record.packetNumber >= _packetRateIncreasePacketNumber) {
|
||||||
|
if (_packetsPerGroup >= _slowStartThreshold) {
|
||||||
|
_packetRateIncreasePacketNumber = _outgoingPacketNumber + 1;
|
||||||
|
}
|
||||||
|
_packetsPerGroup += 1.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatagramSequencer::sendRecordLost(const SendRecord& record) {
|
void DatagramSequencer::sendRecordLost(const SendRecord& record) {
|
||||||
|
@ -263,6 +287,13 @@ void DatagramSequencer::sendRecordLost(const SendRecord& record) {
|
||||||
foreach (const ChannelSpan& span, record.spans) {
|
foreach (const ChannelSpan& span, record.spans) {
|
||||||
getReliableOutputChannel(span.channel)->spanLost(record.packetNumber, _outgoingPacketNumber + 1);
|
getReliableOutputChannel(span.channel)->spanLost(record.packetNumber, _outgoingPacketNumber + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// halve the rate and remember as threshold
|
||||||
|
if (record.packetNumber >= _packetRateDecreasePacketNumber) {
|
||||||
|
_packetsPerGroup = qMax(_packetsPerGroup * 0.5f, 1.0f);
|
||||||
|
_slowStartThreshold = _packetsPerGroup;
|
||||||
|
_packetRateDecreasePacketNumber = _outgoingPacketNumber + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatagramSequencer::appendReliableData(int bytes, QVector<ChannelSpan>& spans) {
|
void DatagramSequencer::appendReliableData(int bytes, QVector<ChannelSpan>& spans) {
|
||||||
|
|
|
@ -99,6 +99,10 @@ public:
|
||||||
/// Returns the intput channel at the specified index, creating it if necessary.
|
/// Returns the intput channel at the specified index, creating it if necessary.
|
||||||
ReliableChannel* getReliableInputChannel(int index = 0);
|
ReliableChannel* getReliableInputChannel(int index = 0);
|
||||||
|
|
||||||
|
/// Starts a packet group.
|
||||||
|
/// \return the number of packets to write in the group
|
||||||
|
int startPacketGroup();
|
||||||
|
|
||||||
/// Starts a new packet for transmission.
|
/// Starts a new packet for transmission.
|
||||||
/// \return a reference to the Bitstream to use for writing to the packet
|
/// \return a reference to the Bitstream to use for writing to the packet
|
||||||
Bitstream& startPacket();
|
Bitstream& startPacket();
|
||||||
|
@ -203,6 +207,12 @@ private:
|
||||||
|
|
||||||
int _maxPacketSize;
|
int _maxPacketSize;
|
||||||
|
|
||||||
|
float _packetsPerGroup;
|
||||||
|
float _packetsToWrite;
|
||||||
|
float _slowStartThreshold;
|
||||||
|
int _packetRateIncreasePacketNumber;
|
||||||
|
int _packetRateDecreasePacketNumber;
|
||||||
|
|
||||||
QHash<int, ReliableChannel*> _reliableOutputChannels;
|
QHash<int, ReliableChannel*> _reliableOutputChannels;
|
||||||
QHash<int, ReliableChannel*> _reliableInputChannels;
|
QHash<int, ReliableChannel*> _reliableInputChannels;
|
||||||
};
|
};
|
||||||
|
|
|
@ -652,7 +652,7 @@ Endpoint::Endpoint(const QByteArray& datagramHeader, Mode mode) :
|
||||||
output->setMessagesEnabled(false);
|
output->setMessagesEnabled(false);
|
||||||
QByteArray bytes;
|
QByteArray bytes;
|
||||||
if (mode == CONGESTION_MODE) {
|
if (mode == CONGESTION_MODE) {
|
||||||
const int HUGE_STREAM_BYTES = 50 * 1024 * 1024;
|
const int HUGE_STREAM_BYTES = 60 * 1024 * 1024;
|
||||||
bytes = createRandomBytes(HUGE_STREAM_BYTES, HUGE_STREAM_BYTES);
|
bytes = createRandomBytes(HUGE_STREAM_BYTES, HUGE_STREAM_BYTES);
|
||||||
|
|
||||||
// initialize the pipeline
|
// initialize the pipeline
|
||||||
|
@ -820,14 +820,23 @@ bool Endpoint::simulate(int iterationNumber) {
|
||||||
bytesReceived += datagram.size();
|
bytesReceived += datagram.size();
|
||||||
_remainingPipelineCapacity += datagram.size();
|
_remainingPipelineCapacity += datagram.size();
|
||||||
}
|
}
|
||||||
|
int packetCount = _sequencer->startPacketGroup();
|
||||||
|
for (int i = 0; i < packetCount; i++) {
|
||||||
|
oldDatagramsSent = datagramsSent;
|
||||||
|
oldBytesSent = bytesSent;
|
||||||
|
|
||||||
Bitstream& out = _sequencer->startPacket();
|
Bitstream& out = _sequencer->startPacket();
|
||||||
out << QVariant();
|
out << QVariant();
|
||||||
_sequencer->endPacket();
|
_sequencer->endPacket();
|
||||||
|
|
||||||
// record the send
|
maxDatagramsPerPacket = qMax(maxDatagramsPerPacket, datagramsSent - oldDatagramsSent);
|
||||||
SendRecord record = { _sequencer->getOutgoingPacketNumber() };
|
maxBytesPerPacket = qMax(maxBytesPerPacket, bytesSent - oldBytesSent);
|
||||||
_sendRecords.append(record);
|
|
||||||
|
// record the send
|
||||||
|
SendRecord record = { _sequencer->getOutgoingPacketNumber() };
|
||||||
|
_sendRecords.append(record);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
} else if (_mode == METAVOXEL_CLIENT_MODE) {
|
} else if (_mode == METAVOXEL_CLIENT_MODE) {
|
||||||
Bitstream& out = _sequencer->startPacket();
|
Bitstream& out = _sequencer->startPacket();
|
||||||
|
|
Loading…
Reference in a new issue