CooloffTime
CooloffTime
#Overview
name: CooloffTime
The value of this variable can be defined or overridden in .ini config files. 9
.ini config files referencing this setting variable.
It is referenced in 22
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of CooloffTime is to control the de-escalation of severity levels in various network-related protection systems within Unreal Engine 5. It represents the amount of time, in seconds, that must pass before the current severity state cools off and de-escalates to a lower level.
This setting variable is primarily used in network security and performance-related subsystems, including:
- RPC DoS (Denial of Service) Detection
- Network Fault Recovery
- DDoS (Distributed Denial of Service) Detection
- General Network Escalation Management
The value of CooloffTime is typically set in configuration files (e.g., .ini files) and can be customized for different severity states or protection systems.
CooloffTime often interacts with other variables such as:
- AutoEscalateTime: The time before automatically escalating to a higher severity level
- Various quota and limit variables specific to each protection system
Developers should be aware of the following when using this variable:
- CooloffTime should be less than AutoEscalateTime to prevent conflicting behavior
- It directly affects the responsiveness and sensitivity of the protection systems
- Setting it too low might cause frequent state changes, while setting it too high could leave the system in a heightened state for too long
Best practices for using CooloffTime include:
- Carefully balance it with other timing variables to create a smooth and effective protection system
- Test different values in various network conditions to find the optimal setting
- Consider the specific needs of your game or application when configuring this value
- Regularly review and adjust the value based on real-world performance and security incident data
#Setting Variables
#References In INI files
Location: <Workspace>/Engine/Config/BaseEngine.ini:1672, section: [DDoSDetection.PersistentBurst]
- INI Section:
DDoSDetection.PersistentBurst
- Raw value:
10
- Is Array:
False
Location: <Workspace>/Engine/Config/BaseEngine.ini:1680, section: [DDoSDetection.DDoS]
- INI Section:
DDoSDetection.DDoS
- Raw value:
10
- Is Array:
False
Location: <Workspace>/Engine/Config/BaseEngine.ini:1688, section: [DDoSDetection.ExpensiveDDoS]
- INI Section:
DDoSDetection.ExpensiveDDoS
- Raw value:
10
- Is Array:
False
Location: <Workspace>/Engine/Config/BaseEngine.ini:1695, section: [DDoSDetection.DebilitatingDDoS]
- INI Section:
DDoSDetection.DebilitatingDDoS
- Raw value:
10
- Is Array:
False
Location: <Workspace>/Engine/Config/BaseEngine.ini:1738, section: [RPCDoSDetection.Hitch]
- INI Section:
RPCDoSDetection.Hitch
- Raw value:
5
- Is Array:
False
Location: <Workspace>/Engine/Config/BaseEngine.ini:1746, section: [RPCDoSDetection.Burst]
- INI Section:
RPCDoSDetection.Burst
- Raw value:
5
- Is Array:
False
Location: <Workspace>/Engine/Config/BaseEngine.ini:1759, section: [RPCDoSDetection.PersistentBurst]
- INI Section:
RPCDoSDetection.PersistentBurst
- Raw value:
5
- Is Array:
False
Location: <Workspace>/Engine/Config/BaseEngine.ini:1775, section: [RPCDoSDetection.DoS]
- INI Section:
RPCDoSDetection.DoS
- Raw value:
10
- Is Array:
False
Location: <Workspace>/Engine/Config/BaseEngine.ini:1791, section: [RPCDoSDetection.ExpensiveDoS]
- INI Section:
RPCDoSDetection.ExpensiveDoS
- Raw value:
10
- Is Array:
False
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Net/RPCDoSDetection.cpp:291
Scope (from outer to inner):
file
function void FRPCDoSStateConfig::ValidateConfig
Source code excerpt:
(RPCRepeatLimitPerPeriod > 0 || RPCRepeatLimitMSPerPeriod > 0));
if (AutoEscalateTime > 0 && AutoEscalateTime < CooloffTime)
{
UE_LOG(LogNet, Warning, TEXT("FRPCDoSStateConfig: AutoEscalateTime must be larger than CooloffTime."));
}
}
int8 FRPCDoSStateConfig::GetHighestTimePeriod() const
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Net/RPCDoSDetection.cpp:321
Scope (from outer to inner):
file
function void FRPCDoSStateConfig::ApplyState
Source code excerpt:
Target.RPCRepeatLimitMSPerPeriod = RPCRepeatLimitMSPerPeriod;
Target.RPCRepeatLimitTimePeriod = RPCRepeatLimitTimePeriod;
Target.CooloffTime = CooloffTime;
Target.AutoEscalateTime = AutoEscalateTime;
Target.ApplyImpliedValues();
}
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Net/RPCDoSDetection.cpp:451
Scope (from outer to inner):
file
function void FRPCDoSDetection::InitConfig
Source code excerpt:
const int8 HighestTimePeriod = CurState.GetHighestTimePeriod();
HighestHistoryRequirment = FMath::Max(HighestHistoryRequirment, (int32)(CurState.CooloffTime + HighestTimePeriod));
MaxRPCTrackingPeriod = FMath::Max(MaxRPCTrackingPeriod, HighestTimePeriod);
}
else
{
UE_LOG(LogNet, Warning, TEXT("RPC DoS Detection failed to load ini section: %s"), *CurSection);
}
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Net/RPCDoSDetection.cpp:540
Scope (from outer to inner):
file
function void FRPCDoSDetection::UpdateSeverity_Private
Source code excerpt:
FRPCDoSStateConfig& PrevState = DetectionSeverity[NewStateIdx-1];
FRPCDoSStateConfig& CurState = DetectionSeverity[NewStateIdx];
int32 CurStateCooloffTime = CurState.CooloffTime;
const TArray<int8>& CurStateTimePeriods = CurState.GetAllTimePeriods();
FRPCDoSCounters CurPerPeriodHistory[16] = {};
check(CounterPerSecHistory.Num() >= CurStateCooloffTime);
// Count backwards through every second of CounterPerSecHistory, whose starting index wraps around like a circular buffer
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Net/RPCDoSDetection.cpp:790
Scope (from outer to inner):
file
function void FRPCDoSDetection::PreTickDispatch
Source code excerpt:
double ActiveStateTime = TimeSeconds - LastMetEscalationConditions;
if (CooloffTime > 0 && ActiveStateTime > CooloffTime)
{
TickScope.UpdateSeverity(*this, ERPCDoSSeverityUpdate::Deescalate, ERPCDoSEscalateReason::Deescalate);
}
else if (AutoEscalateTime > 0 && ActiveStateTime > AutoEscalateTime)
{
TickScope.UpdateSeverity(*this, ERPCDoSSeverityUpdate::AutoEscalate, ERPCDoSEscalateReason::AutoEscalate);
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/Net/RPCDoSDetection.h:239
Scope: file
Source code excerpt:
/** The amount of time, in seconds, before the current DoS severity category cools off and de-escalates */
UPROPERTY(config)
int16 CooloffTime = -1;
/** The amount of time, in seconds, spent in the current DoS severity category before it automatically escalates to the next category */
UPROPERTY(config)
int16 AutoEscalateTime = -1;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/Net/RPCDoSDetection.h:1196
Scope: file
Source code excerpt:
double LastPerSecQuotaBegin = 0.0;
/** Stores enough per second quota history, to allow all DetectionSeverity states to recalculate if their CooloffTime is reached */
TArray<FRPCDoSCounters> CounterPerSecHistory;
/** The last written index of CounterPerSecHistory */
int32 LastCounterPerSecHistoryIdx = 0;
/** Counter history which is precalculated/cached from CounterPerSecHistory, for tracking per-period time (up to a maximum of 16s) */
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Private/Net/Core/Connection/EscalationStates.cpp:15
Scope (from outer to inner):
file
function void FEscalationState::ValidateConfigInternal
Source code excerpt:
Super::ValidateConfigInternal();
if (AutoEscalateTime > 0 && AutoEscalateTime < CooloffTime)
{
UE_LOG(LogNetCore, Warning, TEXT("FEscalationState: AutoEscalateTime must be larger than CooloffTime."));
}
}
void FEscalationState::ValidateTimePeriod(int8& Value, const TCHAR* PropertyName, EValidateTime Requirement/*=EValidateTime::Optional*/)
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Private/Net/Core/Connection/EscalationStates.cpp:196
Scope (from outer to inner):
file
namespace UE
namespace Net
function EEscalateResult FEscalationManager::UpdateSeverity
Source code excerpt:
const TStructOnScope<FEscalationState>& PrevState = EscalationSeverity[NewStateIdx-1];
const TStructOnScope<FEscalationState>& CurState = EscalationSeverity[NewStateIdx];
int32 CurStateCooloffTime = CurState->CooloffTime;
check(CountersPerSecHistory.Num() >= CurStateCooloffTime);
for (FEscalationCounter& CurCounterAlloc : WorkingPerPeriodAlloc)
{
CurCounterAlloc.ResetCounters();
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Private/Net/Core/Connection/EscalationStates.cpp:325
Scope (from outer to inner):
file
namespace UE
namespace Net
function void FEscalationManager::TickRealtime
Source code excerpt:
{
double ActiveStateTime = TimeSeconds - LastMetEscalationConditions;
const double& CooloffTime = State->CooloffTime;
const double& AutoEscalateTime = State->AutoEscalateTime;
bool bUpdatedState = false;
if (CooloffTime > 0 && ActiveStateTime > CooloffTime)
{
bUpdatedState = UpdateSeverity(ESeverityUpdate::Deescalate, EEscalateReason::Deescalate) != EEscalateResult::NoChange;
}
if (!bUpdatedState && AutoEscalateTime > 0 && ActiveStateTime > AutoEscalateTime)
{
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Private/Net/Core/Connection/EscalationStates.cpp:423
Scope (from outer to inner):
file
namespace UE
namespace Net
function int32 FEscalationManager::GetHighestHistoryRequirement
Source code excerpt:
const int8 HighestTimePeriod = CurSeverityConfig->GetHighestTimePeriod();
ReturnVal = FMath::Max(ReturnVal, (int32)(CurSeverityConfig->CooloffTime + HighestTimePeriod));
}
}
return ReturnVal;
}
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Private/Net/Core/Connection/NetConnectionFaultRecoveryBase.cpp:51
Scope (from outer to inner):
file
function EInitStateDefaultsResult FNetFaultState::InitConfigDefaultsInternal
Source code excerpt:
DescalateQuotaFaultsPerPeriod = 6;
EscalateQuotaTimePeriod = 8;
CooloffTime = 10;
AutoEscalateTime = 11;
}
else if (SeverityCategory == TEXT("PersistentFault"))
{
EscalateQuotaFaultsPerPeriod = 64;
EscalateQuotaFaultPercentPerPeriod = 50;
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Private/Net/Core/Connection/NetConnectionFaultRecoveryBase.cpp:61
Scope (from outer to inner):
file
function EInitStateDefaultsResult FNetFaultState::InitConfigDefaultsInternal
Source code excerpt:
DescalateQuotaFaultPercentPerPeriod = 40;
EscalateQuotaTimePeriod = 8;
CooloffTime = 10;
AutoEscalateTime = 20;
bLogEscalate = true;
}
else if (SeverityCategory == TEXT("DisconnectCountdown"))
{
EscalateQuotaFaultPercentPerPeriod = 70;
DescalateQuotaFaultPercentPerPeriod = 56;
EscalateQuotaTimePeriod = 16;
CooloffTime = 10;
AutoEscalateTime = 60;
bLogEscalate = true;
}
else if (SeverityCategory == TEXT("Disconnect"))
{
bCloseConnection = true;
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Private/Net/Core/Misc/DDoSDetection.cpp:140
Scope (from outer to inner):
file
function void FDDoSDetection::InitConfig
Source code excerpt:
GConfig->GetInt(*CurSection, TEXT("PacketTimeLimitMSPerFrame"), CurState.PacketTimeLimitMSPerFrame, GEngineIni);
GConfig->GetInt(*CurSection, TEXT("NetConnPacketTimeLimitMSPerFrame"), CurState.NetConnPacketTimeLimitMSPerFrame, GEngineIni);
GConfig->GetInt(*CurSection, TEXT("CooloffTime"), CurState.CooloffTime, GEngineIni);
if (GConfig->GetInt(*CurSection, TEXT("EscalateTimeQuotaMSPerFrame"), EscalateTime32, GEngineIni))
{
CurState.EscalateTimeQuotaMSPerFrame = IntCastChecked<int16>(EscalateTime32);
}
HighestCooloffTime = FMath::Max(HighestCooloffTime, CurState.CooloffTime);
}
else
{
UE_LOG(LogNetCore, Warning, TEXT("DDoS detection could not find ini section: %s"), *CurSection);
}
}
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Private/Net/Core/Misc/DDoSDetection.cpp:196
Scope (from outer to inner):
file
function void FDDoSDetection::UpdateSeverity
Source code excerpt:
{
FDDoSStateConfig& PrevState = DetectionSeverity[NewState-1];
int32 CurStateCooloffTime = DetectionSeverity[NewState].CooloffTime;
check(CounterPerSecHistory.Num() >= CurStateCooloffTime);
for (int32 SecondsDelta=0; SecondsDelta<CurStateCooloffTime; SecondsDelta++)
{
int32 CurIdx = LastCounterPerSecHistoryIdx - SecondsDelta;
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Private/Net/Core/Misc/DDoSDetection.cpp:286
Scope (from outer to inner):
file
function void FDDoSDetection::PreFrameReceive
Source code excerpt:
FrameAdjustment = static_cast<float>((HitchFrameCount > 0 && HitchFrameCount > HitchFrameTolerance) ? 1.0 : (double)DeltaTime / ExpectedFrameTime);
if (ActiveState > 0 && CooloffTime > 0 && (float)(StartFrameRecvTimestamp - LastMetEscalationConditions) > (float)CooloffTime)
{
UpdateSeverity(false);
}
DetectionSeverity[ActiveState].ApplyAdjustedState(*this, FMath::Max(0.25f, FrameAdjustment));
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Public/Net/Core/Connection/EscalationStates.h:182
Scope: file
Source code excerpt:
/** The amount of time, in seconds, before the current severity state cools off and de-escalates */
UPROPERTY(config)
int16 CooloffTime = -1;
/** The amount of time, in seconds, spent in the current severity state before it automatically escalates to the next state */
UPROPERTY(config)
int16 AutoEscalateTime = -1;
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Public/Net/Core/Connection/EscalationStates.h:584
Scope (from outer to inner):
file
namespace UE
namespace Net
class class FEscalationManager
Source code excerpt:
double LastPerSecQuotaBegin = 0.0;
/** Stores enough per second quota history, to allow all EscalationSeverity states to recalculate if their CooloffTime is reached */
TArray<TArrayView<FEscalationCounter>> CountersPerSecHistory;
/** Allocation for the above array, to reduce indirection */
TArray<FEscalationCounter> CountersPerSecHistoryAlloc;
/** The last written index of CountersPerSecHistory */
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Public/Net/Core/Misc/DDoSDetection.h:89
Scope: file
Source code excerpt:
/** The amount of time, in seconds, before the current DDoS severity category cools off and de-escalates */
int32 CooloffTime;
FDDoSState()
: bSendEscalateAnalytics(true)
, EscalateQuotaPacketsPerSec(-1)
, EscalateQuotaDisconnPacketsPerSec(-1)
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Public/Net/Core/Misc/DDoSDetection.h:101
Scope (from outer to inner):
file
function FDDoSState
Source code excerpt:
, PacketTimeLimitMSPerFrame(-1)
, NetConnPacketTimeLimitMSPerFrame(-1)
, CooloffTime(-1)
{
}
/**
* Whether or not the specified counters and time passed has hit any of the quota's
*
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Public/Net/Core/Misc/DDoSDetection.h:147
Scope (from outer to inner):
file
function void ApplyState
Source code excerpt:
Target.PacketTimeLimitMSPerFrame = PacketTimeLimitMSPerFrame;
Target.NetConnPacketTimeLimitMSPerFrame = NetConnPacketTimeLimitMSPerFrame;
Target.CooloffTime = CooloffTime;
}
/**
* Applies only the per-frame adjusted state (based on expected vs actual framerate), to active DDoS protection.
* ApplyState should be called, first.
*/
#Loc: <Workspace>/Engine/Source/Runtime/Net/Core/Public/Net/Core/Misc/DDoSDetection.h:342
Scope (from outer to inner):
file
class class FDDoSDetection : protected FDDoSPacketCounters, protected FDDoSState
Source code excerpt:
double LastPerSecQuotaBegin;
/** Stores enough per second quota history, to allow all DetectionSeverity states to recalculate if their CooloffTime is reached */
TArray<FDDoSPacketCounters> CounterPerSecHistory;
/** The last written index of CounterPerSecHistory */
int32 LastCounterPerSecHistoryIdx;