You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
srs/trunk/3rdparty/srt-1-fit/srtcore/congctl.h

207 lines
6.6 KiB
C++

/*
* SRT - Secure, Reliable, Transport
* Copyright (c) 2018 Haivision Systems Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#ifndef INC__CONGCTL_H
#define INC__CONGCTL_H
#include <map>
#include <string>
#include <utility>
class CUDT;
class SrtCongestionControlBase;
typedef SrtCongestionControlBase* srtcc_create_t(CUDT* parent);
class SrtCongestion
{
// Temporarily changed to linear searching, until this is exposed
// for a user-defined controller.
// Note that this is a pointer to function :)
static const size_t N_CONTROLLERS = 2;
// The first/second is to mimic the map.
typedef struct { const char* first; srtcc_create_t* second; } NamePtr;
static NamePtr congctls[N_CONTROLLERS];
// This is a congctl container.
SrtCongestionControlBase* congctl;
size_t selector;
void Check();
public:
// If you predict to allow something to be done on controller also
// before it is configured, call this first. If you need it configured,
// you can rely on Check().
bool ready() { return congctl; }
SrtCongestionControlBase* operator->() { Check(); return congctl; }
// In the beginning it's uninitialized
SrtCongestion(): congctl(), selector(N_CONTROLLERS) {}
struct IsName
{
std::string n;
IsName(std::string nn): n(nn) {}
bool operator()(NamePtr np) { return n == np.first; }
};
// You can call select() multiple times, until finally
// the 'configure' method is called.
bool select(const std::string& name)
{
NamePtr* end = congctls+N_CONTROLLERS;
NamePtr* try_selector = std::find_if(congctls, end, IsName(name));
if (try_selector == end)
return false;
selector = try_selector - congctls;
return true;
}
std::string selected_name()
{
if (selector == N_CONTROLLERS)
return "";
return congctls[selector].first;
}
// Copy constructor - important when listener-spawning
// Things being done:
// 1. The congctl is individual, so don't copy it. Set NULL.
// 2. The selected name is copied so that it's configured correctly.
SrtCongestion(const SrtCongestion& source): congctl(), selector(source.selector) {}
// This function will be called by the parent CUDT
// in appropriate time. It should select appropriate
// congctl basing on the value in selector, then
// pin oneself in into CUDT for receiving event signals.
bool configure(CUDT* parent);
// Will delete the pinned in congctl object.
// This must be defined in *.cpp file due to virtual
// destruction.
~SrtCongestion();
enum RexmitMethod
{
SRM_LATEREXMIT,
SRM_FASTREXMIT
};
enum TransAPI
{
STA_MESSAGE = 0x1, // sendmsg/recvmsg functions
STA_BUFFER = 0x2, // send/recv functions
STA_FILE = 0x3, // sendfile/recvfile functions
};
enum TransDir
{
STAD_RECV = 0,
STAD_SEND = 1
};
};
class SrtCongestionControlBase
{
protected:
// Here can be some common fields
CUDT* m_parent;
double m_dPktSndPeriod;
double m_dCWndSize;
//int m_iBandwidth; // NOT REQUIRED. Use m_parent->bandwidth() instead.
double m_dMaxCWndSize;
//int m_iMSS; // NOT REQUIRED. Use m_parent->MSS() instead.
//int32_t m_iSndCurrSeqNo; // NOT REQUIRED. Use m_parent->sndSeqNo().
//int m_iRcvRate; // NOT REQUIRED. Use m_parent->deliveryRate() instead.
//int m_RTT; // NOT REQUIRED. Use m_parent->RTT() instead.
//char* m_pcParam; // Used to access m_llMaxBw. Use m_parent->maxBandwidth() instead.
// Constructor in protected section so that this class is semi-abstract.
SrtCongestionControlBase(CUDT* parent);
public:
// This could be also made abstract, but this causes a linkage
// problem in C++: this would constitute the first virtual method,
// and C++ compiler uses the location of the first virtual method as the
// file to which it also emits the virtual call table. When this is
// abstract, there would have to be simultaneously either defined
// an empty method in congctl.cpp file (obviously never called),
// or simply left empty body here.
virtual ~SrtCongestionControlBase() { }
// All these functions that return values interesting for processing
// by CUDT can be overridden. Normally they should refer to the fields
// and these fields should keep the values as a state.
virtual double pktSndPeriod_us() { return m_dPktSndPeriod; }
virtual double cgWindowSize() { return m_dCWndSize; }
virtual double cgWindowMaxSize() { return m_dMaxCWndSize; }
virtual int64_t sndBandwidth() { return 0; }
// If user-defined, will return nonzero value.
// If not, it will be internally calculated.
virtual int RTO() { return 0; }
// Maximum number of packets to trigger ACK sending.
// Specifies the number of packets to receive before sending the ACK.
// Used by CUDT together with ACKTimeout_us() to trigger ACK packet sending.
virtual int ACKMaxPackets() const { return 0; }
// Periodical interval to send an ACK, in microseconds.
// If user-defined, this value will be used to calculate
// the next ACK time every time ACK is considered to be sent (see CUDT::checkTimers).
// Otherwise this will be calculated internally in CUDT, normally taken
// from CUDT::COMM_SYN_INTERVAL_US.
virtual int ACKTimeout_us() const { return 0; }
// Called when the settings concerning m_llMaxBW were changed.
// Arg 1: value of CUDT::m_llMaxBW
// Arg 2: value calculated out of CUDT::m_llInputBW and CUDT::m_iOverheadBW.
virtual void updateBandwidth(int64_t, int64_t) {}
virtual bool needsQuickACK(const CPacket&)
{
return false;
}
// Particular controller is allowed to agree or disagree on the use of particular API.
virtual bool checkTransArgs(SrtCongestion::TransAPI , SrtCongestion::TransDir , const char* /*buffer*/, size_t /*size*/, int /*ttl*/, bool /*inorder*/)
{
return true;
}
virtual SrtCongestion::RexmitMethod rexmitMethod() = 0; // Implementation enforced.
virtual uint64_t updateNAKInterval(uint64_t nakint_tk, int rcv_speed, size_t loss_length)
{
if (rcv_speed > 0)
nakint_tk += (loss_length * uint64_t(1000000) / rcv_speed) * CTimer::getCPUFrequency();
return nakint_tk;
}
virtual uint64_t minNAKInterval()
{
return 0; // Leave default
}
};
#endif