UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
NetPacketNotify.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "EngineLogs.h"
6#include "HAL/UnrealMemory.h"
7#include "Logging/LogMacros.h"
10#include "Util/SequenceNumber.h"
12
13#if (UE_BUILD_SHIPPING || UE_BUILD_TEST)
14# define UE_NET_ENABLE_PACKET_NOTIFY_LOG 0
15#else
16# define UE_NET_ENABLE_PACKET_NOTIFY_LOG 1
17#endif
18
19#if UE_NET_ENABLE_PACKET_NOTIFY_LOG
20# define UE_LOG_PACKET_NOTIFY(Format, ...) UE_LOG(LogNetTraffic, Verbose, Format, ##__VA_ARGS__)
21#else
22# define UE_LOG_PACKET_NOTIFY(...)
23#endif
24
25#define UE_LOG_PACKET_NOTIFY_WARNING(Format, ...) UE_LOG(LogNetTraffic, Warning, Format, ##__VA_ARGS__)
26
27struct FBitWriter;
28struct FBitReader;
29
30namespace UE::Net::Private
31{
33}
34
39{
40public:
41 enum { SequenceNumberBits = 14 };
43
46
54
57
60
62 void AckSeq(SequenceNumberT Seq) { AckSeq(Seq, true); }
63
65 void NakSeq(SequenceNumberT Seq) { AckSeq(Seq, false); }
66
69
74 bool WriteHeader(FBitWriter& Writer, bool bRefresh = false);
75
77 bool ReadHeader(FNotificationHeader& Data, FBitReader& Reader) const;
78
83 {
84 if (NotificationData.Seq > InSeq && NotificationData.AckedSeq >= OutAckSeq && OutSeq > NotificationData.AckedSeq)
85 {
86 return SequenceNumberT::Diff(NotificationData.Seq, InSeq);
87 }
88 else
89 {
90 return 0;
91 }
92 }
93
101 template<class Functor>
102 SequenceNumberT::DifferenceT Update(const FNotificationHeader& NotificationData, Functor&& InFunc);
103
105 const SequenceHistoryT& GetInSeqHistory() const { return InSeqHistory; }
106
108 SequenceNumberT GetInSeq() const { return InSeq; }
109
111 SequenceNumberT GetInAckSeq() const { return InAckSeq; }
112
114 SequenceNumberT GetOutSeq() const { return OutSeq; }
115
117 SequenceNumberT GetOutAckSeq() const { return OutAckSeq; }
118
120 bool CanSend() const { SequenceNumberT NextOutSeq = OutSeq; ++NextOutSeq; return NextOutSeq >= OutAckSeq; }
121
127
130
132 bool IsWaitingForSequenceHistoryFlush() const { return WaitingForFlushSeqAck > OutAckSeq; }
133
134private:
135 struct FSentAckData
136 {
137 SequenceNumberT OutSeq; // Not needed... just to verify that things work as expected
138 SequenceNumberT InAckSeq;
139 };
141
142 AckRecordT AckRecord; // Track acked seq for each sent packet to track size of ack history
143 SIZE_T WrittenHistoryWordCount; // Bookkeeping to track if we can update data
144 SequenceNumberT WrittenInAckSeq; // When we call CommitAndIncrementOutSequence this will be committed along with the current outgoing sequence number for bookkeeping
145
146 // Track incoming sequence data
147 SequenceHistoryT InSeqHistory; // BitBuffer containing a bitfield describing the history of received packets
148 SequenceNumberT InSeq; // Last sequence number received and accepted from remote
149 SequenceNumberT InAckSeq; // Last sequence number received from remote that we have acknowledged, this is needed since we support accepting a packet but explicitly not acknowledge it as received.
150 SequenceNumberT InAckSeqAck; // Last sequence number received from remote that we have acknowledged and also knows that the remote has received the ack, used to calculate how big our history must be
151 SequenceNumberT WaitingForFlushSeqAck;
152
153 // Track outgoing sequence data
154 SequenceNumberT OutSeq; // Outgoing sequence number
155 SequenceNumberT OutAckSeq; // Last sequence number that we know that the remote side have received.
156
157private:
158
161
162 // Returns true if sequence history contains any packets marked as received for which we have not yet received an ack
163 bool GetHasUnacknowledgedAcks() const;
164
165 // Returns true if we can acknowledge the Seq without overshooting the sequence history
166 bool WillSequenceFitInSequenceHistory(SequenceNumberT Seq) const;
167
168 // Initiates a wait for a flush of the sequence history
169 void SetWaitForSequenceHistoryFlush();
170
171 template<class Functor>
172 inline void ProcessReceivedAcks(const FNotificationHeader& NotificationData, Functor&& InFunc);
173 void AckSeq(SequenceNumberT AckedSeq, bool IsAck);
174
175#if WITH_AUTOMATION_WORKER
176 friend UE::Net::Private::FNetPacketNotifyTestUtil;
177#endif
178};
179
181{
182 const SequenceNumberT SequenceLength = OutSeq - OutAckSeq;
183 return SequenceLength > MaxSequenceHistoryLength || (SafetyMargin >= MaxSequenceHistoryLength) || (SequenceLength.Get() > (MaxSequenceHistoryLength - SafetyMargin));
184}
185
186template<class Functor>
188{
190
191 if (InSeqDelta > 0)
192 {
193 UE_LOG_PACKET_NOTIFY(TEXT("FNetPacketNotify::Update - Seq %u, InSeq %u"), NotificationData.Seq.Get(), InSeq.Get());
194
195 ProcessReceivedAcks(NotificationData, InFunc);
196
197 return InternalUpdate(NotificationData, InSeqDelta);
198 }
199 else
200 {
201 return 0;
202 }
203}
204
205template<class Functor>
206void FNetPacketNotify::ProcessReceivedAcks(const FNotificationHeader& NotificationData, Functor&& InFunc)
207{
208 if (NotificationData.AckedSeq > OutAckSeq)
209 {
211
212 UE_LOG_PACKET_NOTIFY(TEXT("Notification::ProcessReceivedAcks - AckedSeq: %u, OutAckSeq: %u AckCount: %u"), NotificationData.AckedSeq.Get(), OutAckSeq.Get(), AckCount);
213
214 // Update InAckSeqAck used to track the needed number of bits to transmit our ack history
215 // Note: As we might reset sequence history we need to check if we already have advanced the InAckSeqAck
216 const SequenceNumberT NewInAckSeqAck = UpdateInAckSeqAck(AckCount, NotificationData.AckedSeq);
217 if (NewInAckSeqAck > InAckSeqAck)
218 {
219 InAckSeqAck = NewInAckSeqAck;
220 }
221
222 // ExpectedAck = OutAckSeq + 1
223 SequenceNumberT CurrentAck(OutAckSeq);
224 ++CurrentAck;
225
226 // Make sure that we only look at the sequence history bit included in the notification data as the sequence history might have been reset,
227 // in which case we might not receive the max size history even though the ack-count is bigger than the history
229
230 // Warn if the received sequence number is greater than our history buffer, since if that is the case we have to treat the data as lost
231 // Note: This should normally not be a problem since we try to flush the sequence history before allowing an overshoot of the sequence history window on the sending side.
232 // If this occurs with no hitches on server or client, there might be reason to investigate if too much data is being sent in which case the the size sequence history might have to be increased.
234 {
235 UE_LOG_PACKET_NOTIFY_WARNING(TEXT("FNetPacketNotify::ProcessReceivedAcks - Missed Acks: AckedSeq: %u, OutAckSeq: %u, FirstMissingSeq: %u Count: %u"), NotificationData.AckedSeq.Get(), OutAckSeq.Get(), CurrentAck.Get(), AckCount - (SequenceNumberT::DifferenceT)(SequenceHistoryT::Size));
236 }
237
238 // Everything not found in the history buffer is treated as lost
239 while (AckCount > HistoryBits)
240 {
241 --AckCount;
242 InFunc(CurrentAck, false);
243 ++CurrentAck;
244 }
245
246 // For sequence numbers contained in the history we lookup the delivery status from the history
247 while (AckCount > 0)
248 {
249 --AckCount;
250 UE_LOG_PACKET_NOTIFY(TEXT("Notification::ProcessReceivedAcks Seq: %u - IsAck: %u HistoryIndex: %u"), CurrentAck.Get(), NotificationData.History.IsDelivered(AckCount) ? 1u : 0u, AckCount);
251 InFunc(CurrentAck, NotificationData.History.IsDelivered(AckCount));
252 ++CurrentAck;
253 }
254 OutAckSeq = NotificationData.AckedSeq;
255
256 // Are we done waiting for an reset of the ack history?
257 if (OutAckSeq > WaitingForFlushSeqAck)
258 {
259 WaitingForFlushSeqAck = OutAckSeq;
260 }
261 }
262}
263
264
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
void Init()
Definition LockFreeList.h:4
#define UE_LOG_PACKET_NOTIFY(Format,...)
Definition NetPacketNotify.h:20
#define UE_LOG_PACKET_NOTIFY_WARNING(Format,...)
Definition NetPacketNotify.h:25
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition NetPacketNotify.h:39
SequenceNumberT GetInSeq() const
Definition NetPacketNotify.h:108
SequenceNumberT GetOutSeq() const
Definition NetPacketNotify.h:114
TSequenceHistory< MaxSequenceHistoryLength > SequenceHistoryT
Definition NetPacketNotify.h:45
SequenceNumberT::DifferenceT Update(const FNotificationHeader &NotificationData, Functor &&InFunc)
Definition NetPacketNotify.h:187
bool WriteHeader(FBitWriter &Writer, bool bRefresh=false)
Definition NetPacketNotify.cpp:203
bool IsSequenceWindowFull(uint32 SafetyMargin=0U) const
Definition NetPacketNotify.h:180
const SequenceHistoryT & GetInSeqHistory() const
Definition NetPacketNotify.h:105
bool IsWaitingForSequenceHistoryFlush() const
Definition NetPacketNotify.h:132
SequenceNumberT::DifferenceT GetSequenceDelta(const FNotificationHeader &NotificationData)
Definition NetPacketNotify.h:82
SequenceNumberT GetOutAckSeq() const
Definition NetPacketNotify.h:117
void AckSeq(SequenceNumberT Seq)
Definition NetPacketNotify.h:62
bool ReadHeader(FNotificationHeader &Data, FBitReader &Reader) const
Definition NetPacketNotify.cpp:236
SequenceNumberT::DifferenceT GetCurrentSequenceHistoryLength() const
Definition NetPacketNotify.cpp:15
bool CanSend() const
Definition NetPacketNotify.h:120
TSequenceNumber< SequenceNumberBits, uint16 > SequenceNumberT
Definition NetPacketNotify.h:44
void NakSeq(SequenceNumberT Seq)
Definition NetPacketNotify.h:65
@ MaxSequenceHistoryLength
Definition NetPacketNotify.h:42
FNetPacketNotify()
Definition NetPacketNotify.cpp:9
@ SequenceNumberBits
Definition NetPacketNotify.h:41
SequenceNumberT CommitAndIncrementOutSeq()
Definition NetPacketNotify.cpp:255
SequenceNumberT GetInAckSeq() const
Definition NetPacketNotify.h:111
Definition ResizableCircularQueue.h:21
Definition SequenceHistory.h:15
static constexpr SIZE_T BitsPerWord
Definition SequenceHistory.h:19
static constexpr SIZE_T Size
Definition SequenceHistory.h:22
Definition SequenceNumber.h:13
SequenceT Get() const
Definition SequenceNumber.h:34
static DifferenceT Diff(TSequenceNumber A, TSequenceNumber B)
Definition SequenceNumber.h:98
int32 DifferenceT
Definition SequenceNumber.h:18
Definition NetworkVersion.cpp:28
Definition BitReader.h:25
Definition BitWriter.h:22
Definition NetPacketNotify.h:48
SequenceNumberT Seq
Definition NetPacketNotify.h:51
SequenceNumberT AckedSeq
Definition NetPacketNotify.h:52
SIZE_T HistoryWordCount
Definition NetPacketNotify.h:50
SequenceHistoryT History
Definition NetPacketNotify.h:49