UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
TransactionTwo.inl
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5namespace UE::IoStore::HTTP
6{
7
10
12bool IsContentless(uint32 StatusCode)
13{
14 return (StatusCode < 200) | (StatusCode == 204) | (StatusCode == 304);
15}
16
18bool IsStatusCodeOk(uint32 StatusCode)
19{
20 enum { MinCode = 100, MaxCode = 999 };
21 return uint32(StatusCode - MinCode) <= uint32(MaxCode - MinCode);
22}
23
24} // namespace UE::IoStore::HTTP
25
26
27
29#if !defined(WITH_NGHTTP2)
30# define WITH_NGHTTP2 0
31# if defined(__has_include)
32# if __has_include(<nghttp2/nghttp2.h>)
33# undef WITH_NGHTTP2
34# define WITH_NGHTTP2 1
35# endif
36# endif
37#endif
38
39#if !defined(IAS_HTTP_WITH_TWO)
40# define IAS_HTTP_WITH_TWO WITH_NGHTTP2
41#endif
42
43#if IAS_HTTP_WITH_TWO
44
46#if defined(_MSC_VER)
47# define NGHTTP2_NO_SSIZE_T
48#endif
49#if PLATFORM_MICROSOFT & !defined(NGHTTP2_STATICLIB)
50# define NGHTTP2_STATICLIB
51#endif
52
53#include <nghttp2/nghttp2.h>
54
55#if PLATFORM_MICROSOFT & !defined(NGHTTP2_STATICLIB)
56# undef NGHTTP2_STATICLIB
57#endif
58#if defined(_MSC_VER)
59# undef NGHTTP2_NO_SSIZE_T
60#endif
61
62namespace UE::IoStore::HTTP
63{
64
65namespace DetailTwo
66{
67
69struct FFrame
70{
71 enum class EType : uint8
72 {
73 Data, // = 0x00,
74 Headers, // = 0x01,
75 Priority, // = 0x02,
76 RstStream, // = 0x03,
77 Settings, // = 0x04,
78 PushPromise, // = 0x05,
79 Ping, // = 0x06,
80 Goaway, // = 0x07,
81 WindowUpdate, // = 0x08,
82 Continuation, // = 0x09,
83 _Num,
84 };
85
86 enum : uint8
87 {
88 Flag_Padding = 0x08,
89 Flag_EndHeaders = 0x04,
90 Flag_EndStream = 0x01,
91 };
92
93 uint8 Size[3];
94 EType Type;
96 uint8 Id[4];
97
98 int32 IsPertinent() const { return (Id[3] & 1) != 0; }
99 uint32 GetSize() const { return (Size[0] << 16u) | (Size[1] << 8u) | Size[2]; }
100 uint32 GetId() const { return (Id[0] << 24u) | (Id[1] << 16u) | (Id[2] << 8u) | Id[3]; }
101 uint32 GetIdFast() const { return Id[3]; }
102};
103static_assert(sizeof(FFrame) == 9);
104
105
106
108class FBufferNg
109{
110public:
111 FBufferNg() = default;
112 ~FBufferNg() { if (Inner != nullptr) nghttp2_rcbuf_decref(Inner); }
114 FBufferNg(FBufferNg&& Rhs) { Swap(Inner, Rhs.Inner); }
115 FBufferNg(const FBufferNg&) = delete;
116 FBufferNg& operator = (FBufferNg&& Rhs) { Swap(Inner, Rhs.Inner); return *this; }
117 FBufferNg& operator = (const FBufferNg&) = delete;
118
119 FAnsiStringView Get() const
120 {
121 check(Inner != nullptr);
123 return { (char*)(Ret.base), int32(Ret.len) };
124 }
125
126private:
127 nghttp2_rcbuf* Inner = nullptr;
128};
129
131struct FHeaderNg
132{
133 FBufferNg Key;
135};
136
137
138
140class FDriverHeaders
141{
142public:
143 FDriverHeaders() = default;
145
146private:
147 friend class FDriverNg;
148
149 const nghttp2_nv* GetData() const { return Headers.GetData(); }
150 int32 Num() const { return Headers.Num(); }
151 TArray<nghttp2_nv> Headers;
152
154};
155
157void FDriverHeaders::Add(FAnsiStringView Key, FAnsiStringView Value)
158{
160 (uint8*)Key.GetData(),
161 (uint8*)Value.GetData(),
162 size_t(Key.Len()),
163 size_t(Value.Len()),
165 };
166 Headers.Add(MoveTemp(Header));
167}
168
169
170
172class FDriverNg
173{
174public:
175 FDriverNg(FTlsPeer& Peer);
176 bool IsUsingTls() const;
177 void GoAway(FTlsPeer& Peer);
178 FOutcome Handshake(FTlsPeer& Peer);
179 FOutcome GetTransactId(FTlsPeer& Peer);
180 FTransactId Submit(const FDriverHeaders& Headers);
181 FOutcome Send(FTlsPeer& Peer);
182 FOutcome RecvResponse(FTlsPeer& Peer, TArray<FHeaderNg>* Sink);
183 FOutcome RecvBody(FTlsPeer& Peer, FMutableMemoryView Dest);
184
185private:
186 FOutcome Tick(FTlsPeer& Peer);
187 FOutcome TickInner(FTlsPeer& Peer);
188 FOutcome PumpSend(FTlsPeer& Peer);
189 FOutcome PumpRecv(FTlsPeer& Peer, FMemoryView Data);
191 nghttp2_session* Session;
192 TArray<FHeaderNg>* ResponseHeaders = nullptr;
195 bool bWithTls;
196 uint8 RecvBuffer[512 - sizeof(FFrame)];
197 union
198 {
201 };
202
204};
205
207FDriverNg::FDriverNg(FTlsPeer& Peer)
208: bWithTls(Peer.IsUsingTls())
209{
210 struct FStaticsNg
211 {
213 {
215 }
217 };
218
219 static FStaticsNg Statics;
220 if (Statics.Instance == nullptr)
221 {
222 nghttp2_session_callbacks* Callbacks;
224
226 Callbacks,
227 [] (nghttp2_session*, const nghttp2_frame*, nghttp2_rcbuf* Name, nghttp2_rcbuf* Value, uint8_t, void* UserData) -> int32
228 {
229 auto* This = (FDriverNg*)UserData;
230 return This->OnHeader(Name, Value);
231 }
232 );
233
234 Statics.Instance = Callbacks;
235 }
236
237 static nghttp2_mem Mem = {
238 .mem_user_data = nullptr,
239 .malloc = [] (size_t Size, void*) { return FMemory::Malloc(Size); },
240 .free = [] (void* Ptr, void*) { return FMemory::Free(Ptr); },
241 .calloc = [] (size_t Count, size_t Size, void*) { return FMemory::MallocZeroed(Count * Size); },
242 .realloc = [] (void* Ptr, size_t Size, void*) { return FMemory::Realloc(Ptr, Size); },
243 };
244
245 RecvRemaining = 0 - int32(sizeof(RecvFrame));
246
247 nghttp2_session_client_new3(&Session, Statics.Instance, this, nullptr, &Mem);
248
249 // Perhaps in the future a window size can be picked - or adjusted - by
250 // monitoring latency and throughput.
251 /*
252 nghttp2_session_set_local_window_size(Session, 0, 0, 256 << 10);
253 */
254}
255
257void FDriverNg::GoAway(FTlsPeer& Peer)
258{
259 if (Session != nullptr)
260 {
262 PumpSend(Peer);
263 nghttp2_session_del(Session);
264 }
265}
266
268bool FDriverNg::IsUsingTls() const
269{
270 return bWithTls;
271}
272
274FOutcome FDriverNg::PumpSend(FTlsPeer& Peer)
275{
276 for (uint32 Sent = 0;;)
277 {
278 if (SendPending.IsEmpty())
279 {
280 const uint8* Data = nullptr;
281 int32 Result = int32(nghttp2_session_mem_send2(Session, &Data));
282 if (Result < 0)
283 {
284 const char* Message = nghttp2_strerror(Result);
285 return FOutcome::Error(Message);
286 }
287
288 if (Result == 0)
289 {
290 return FOutcome::Ok(Sent);
291 }
292
293 SendPending = { Data, uint32(Result) };
294 }
295
296 const char* Data = (char*)(SendPending.GetData());
297 uint32 Size = uint32(SendPending.GetSize());
298 FOutcome Outcome = Peer.Send((char*)Data, Size);
299 if (Outcome.IsError())
300 {
301 return Outcome;
302 }
303
304 if (Outcome.IsOk())
305 {
306 int32 Result = Outcome.GetResult();
307 Sent += Result;
308
309 SendPending = SendPending.Mid(Result);
310 if (SendPending.IsEmpty())
311 {
312 continue;
313 }
314 }
315
316 check(!SendPending.IsEmpty());
317 return FOutcome::Waiting();
318 }
319}
320
322FOutcome FDriverNg::PumpRecv(FTlsPeer& Peer, FMemoryView Data)
323{
324 int32 Result = int32(nghttp2_session_mem_recv2(Session, (uint8*)Data.GetData(), Data.GetSize()));
325
326 if (Result < 0)
327 {
328 const char* Message = nghttp2_strerror(Result);
329 return FOutcome::Error(Message);
330 }
331
332 if (Result != int32(Data.GetSize()))
333 {
334 return FOutcome::Error("Not enough data consumed");
335 }
336
337 if (nghttp2_session_want_write(Session))
338 {
339 // We'll not care about the outcome here. If an error occurred it will
340 // surface later and data-waits will solved themselves later.
341 PumpSend(Peer);
342 }
343
344 return FOutcome::Ok();
345}
346
348FOutcome FDriverNg::Handshake(FTlsPeer& Peer)
349{
350 nghttp2_submit_settings(Session, NGHTTP2_FLAG_NONE, nullptr, 0);
351 FOutcome Outcome = PumpSend(Peer);
352 return Outcome.IsError() ? Outcome : FOutcome::Ok();
353}
354
356FOutcome FDriverNg::GetTransactId(FTlsPeer& Peer)
357{
358 if (RecvRemaining >= 0 && RecvFrame.IsPertinent())
359 {
360 uint32 Id = RecvFrame.GetId();
361 return FOutcome::Ok(Id);
362 }
363
364 return Tick(Peer);
365}
366
368FOutcome FDriverNg::Tick(FTlsPeer& Peer)
369{
370 while (true)
371 {
372 FOutcome Outcome = TickInner(Peer);
373 if (!Outcome.IsWaiting() || (Outcome.GetResult() == 0))
374 {
375 return Outcome;
376 }
377 }
378}
379
381FOutcome FDriverNg::TickInner(FTlsPeer& Peer)
382{
383 FMutableMemoryView Dest(RecvBuffer, sizeof(RecvBuffer) + sizeof(RecvFrame));
384 if (RecvRemaining < 0)
385 {
386 Dest = Dest.Right(0 - RecvRemaining);
387 }
388 else if (RecvRemaining <= int32(sizeof(RecvBuffer)))
389 {
390 Dest = Dest.Right(RecvRemaining + sizeof(RecvFrame));
391 }
392 else
393 {
394 Dest = Dest.Left(sizeof(RecvBuffer));
395 }
396
397 FOutcome Outcome = Peer.Recv((char*)(Dest.GetData()), int32(Dest.GetSize()));
398 if (!Outcome.IsOk())
399 {
400 return Outcome;
401 }
402
403 int32 Result = Outcome.GetResult();
404 Dest = Dest.Left(Result);
405
407 if (const uint8* End = (uint8*)(Dest.GetDataEnd()); End > RecvFrameData)
408 {
410 Dest = Dest.LeftChop(FrameView.GetSize());
411 }
412
413 if (!Dest.IsEmpty() && (Outcome = PumpRecv(Peer, Dest)).IsError())
414 {
415 return Outcome;
416 }
417
418 if (FrameView.IsEmpty())
419 {
420 check(RecvRemaining >= int32(Dest.GetSize()));
421 if ((RecvRemaining -= int32(Dest.GetSize())) == 0)
422 {
423 RecvRemaining = 0 - int32(sizeof(RecvFrame));
424 }
425 return FOutcome::Waiting(Dest.GetDataEnd() == RecvFrameData);
426 }
427
428 if (Result = int32(FrameView.GetSize() - sizeof(RecvFrame)); Result < 0)
429 {
430 RecvRemaining = Result;
431 return FOutcome::Waiting();
432 }
433
434 if ((Outcome = PumpRecv(Peer, FrameView)).IsError())
435 {
436 return Outcome;
437 }
438
439 RecvRemaining = RecvFrame.GetSize();
440 if (RecvFrame.IsPertinent())
441 {
442 uint32 Id = RecvFrame.GetId();
443 return FOutcome::Ok(Id);
444 }
445
446 if (RecvRemaining == 0)
447 {
448 RecvRemaining = 0 - int32(sizeof(RecvFrame));
449 }
450
451 return FOutcome::Waiting(1);
452}
453
455FTransactId FDriverNg::Submit(const FDriverHeaders& Headers)
456{
457 return nghttp2_submit_request2(Session, nullptr, Headers.GetData(),
458 Headers.Num(), nullptr, this);
459}
460
462FOutcome FDriverNg::Send(FTlsPeer& Peer)
463{
464 return PumpSend(Peer);
465}
466
468FOutcome FDriverNg::RecvResponse(FTlsPeer& Peer, TArray<FHeaderNg>* Sink)
469{
470 if (RecvFrame.Type == FFrame::EType::RstStream)
471 {
472 return FOutcome::Error("Received stream reset");
473 }
474
475 // Assume if we're filling we are expecting something
476 check(RecvRemaining > 0);
477 check(RecvFrame.Type == FFrame::EType::Headers);
478
479 ResponseHeaders = Sink;
480 ON_SCOPE_EXIT { ResponseHeaders = nullptr; };
481
482 while (true)
483 {
484 int32 EndOfHeaders = (RecvFrame.Flags & FFrame::Flag_EndHeaders);
485 uint32 ThisId = RecvFrame.GetId();
486
487 if (EndOfHeaders)
488 {
489 RecvFrame = {};
490 }
491
492 FOutcome Outcome = Tick(Peer);
493 if (Outcome.IsError()) return Outcome;
494 if (EndOfHeaders) return FOutcome::Ok();
495 if (Outcome.GetResult() != ThisId) return FOutcome::WaitStream();
496 }
497}
498
500FOutcome FDriverNg::RecvBody(FTlsPeer& Peer, FMutableMemoryView Dest)
501{
502 if (RecvFrame.Type == FFrame::EType::RstStream)
503 {
504 return FOutcome::Error("Received stream reset");
505 }
506
507 check(RecvRemaining >= 0);
508 check(RecvFrame.Type == FFrame::EType::Data);
509
510 for (uint32 RecvSize = 0;;)
511 {
512 int32 EndOfStream = (RecvFrame.Flags & FFrame::Flag_EndStream);
513
515 if (View.IsEmpty())
516 {
517 if (EndOfStream)
518 {
519 RecvFrame = {};
520 return FOutcome::Ok(RecvSize);
521 }
522
523 return FOutcome::WaitBuffer(RecvSize);
524 }
525
526 FOutcome Outcome = Peer.Recv((char*)View.GetData(), int32(View.GetSize()));
527 if (!Outcome.IsOk())
528 {
529 if (Outcome.IsError())
530 {
531 return Outcome;
532 }
533 return FOutcome::Waiting(RecvSize);
534 }
535
536 int32 Result = Outcome.GetResult();
537 RecvRemaining -= Result;
538 RecvSize += Result;
539 Dest = Dest.Mid(Result);
540
541 if ((Outcome = PumpRecv(Peer, View.Left(Result))).IsError())
542 {
543 return Outcome;
544 }
545
546 // more of this frame to go?
547 if (RecvRemaining > 0)
548 {
549 continue;
550 }
551
553
554 // End of the road?
555 if (EndOfStream)
556 {
557 RecvFrame = {};
558 return FOutcome::Ok(RecvSize);
559 }
560
561 uint32 ThisId = RecvFrame.GetId();
562 Outcome = Tick(Peer);
563 if (Outcome.IsError()) return Outcome;
564 if (ThisId != Outcome.GetResult()) return FOutcome::WaitBuffer(RecvSize);
565 }
566}
567
569int32 FDriverNg::OnHeader(nghttp2_rcbuf* Name, nghttp2_rcbuf* Value)
570{
571 if (ResponseHeaders == nullptr)
572 {
574 }
575
577 ResponseHeaders->Add(MoveTemp(Header));
578 return 0;
579}
580
581
582
584class FBase
585{
586public:
587 FBase(FDriverNg& InDriver);
588
589protected:
590 FDriverNg& GetDriver();
591
592private:
593 FDriverNg& Driver;
594};
595
597FBase::FBase(FDriverNg& InDriver)
598: Driver(InDriver)
599{
600}
601
603FDriverNg& FBase::GetDriver()
604{
605 return Driver;
606}
607
608
609
611class FRequest
612 : public FBase
613{
614public:
615 using FBase::FBase;
616
617 void Begin(FAnsiStringView Host, FAnsiStringView Method, FAnsiStringView Path);
618 void AddHeader(FAnsiStringView Key, FAnsiStringView Value);
619 FTransactId End(bool bKeepAlive);
620 FOutcome TrySendRequest(FTlsPeer& Peer);
621
622protected:
623 FTransactId GetTransactId() const;
624
625private:
626 FDriverHeaders RequestHeaders;
627 FTransactId Id;
628};
629
631void FRequest::Begin(FAnsiStringView Host, FAnsiStringView Method, FAnsiStringView Path)
632{
633 FAnsiStringView Scheme = GetDriver().IsUsingTls() ? "https" : "http";
634 RequestHeaders.Add(":method", Method);
635 RequestHeaders.Add(":path", Path);
636 RequestHeaders.Add(":authority", Host);
637 RequestHeaders.Add(":scheme", Scheme);
638}
639
641void FRequest::AddHeader(FAnsiStringView Key, FAnsiStringView Value)
642{
643 check(!Key.Equals("connection", ESearchCase::IgnoreCase));
644
645#if UE_BUILD_DEVELOPMENT
646 for (uint32 Char : Key)
647 {
648 if (uint32(Char - 'A') > uint32('Z' - 'A'))
649 {
650 check("header keys must be lowercase");
651 }
652 }
653#endif
654 RequestHeaders.Add(Key, Value);
655}
656
658FTransactId FRequest::GetTransactId() const
659{
660 return Id;
661}
662
664FTransactId FRequest::End(bool /*bKeepAlive*/)
665{
666 Id = GetDriver().Submit(RequestHeaders);
667 return Id;
668}
669
671FOutcome FRequest::TrySendRequest(FTlsPeer& Peer)
672{
673 return GetDriver().Send(Peer);
674}
675
676
677
679class FStatusHeaders
680 : public FRequest
681{
682public:
683 using FRequest::FRequest;
684
685 FOutcome TryRecvResponse(FTlsPeer& Peer);
686 bool IsKeepAlive() const;
687 uint32 GetStatusCode() const;
688 FAnsiStringView GetStatusMessage() const;
689 int64 GetContentLength() const;
690 bool IsChunked() const;
691 void ReadHeaders(FResponse::FHeaderSink Sink) const;
692
693private:
694 TArray<FHeaderNg> ResponseHeaders;
695 int64 ContentLength = -1;
696 uint32 StatusCode = 0;
697};
698
700bool FStatusHeaders::IsKeepAlive() const
701{
702 return true;
703}
704
706uint32 FStatusHeaders::GetStatusCode() const
707{
708 return StatusCode;
709}
710
712FAnsiStringView FStatusHeaders::GetStatusMessage() const
713{
714 return "";
715}
716
718int64 FStatusHeaders::GetContentLength() const
719{
720 return ContentLength;
721}
722
724bool FStatusHeaders::IsChunked() const
725{
726 return ContentLength < 0;
727}
728
730void FStatusHeaders::ReadHeaders(FResponse::FHeaderSink Sink) const
731{
732 for (const FHeaderNg& Header : ResponseHeaders)
733 {
734 FAnsiStringView Key = Header.Key.Get();
735 FAnsiStringView Value = Header.Value.Get();
736 if (!Sink(Key, Value))
737 {
738 break;
739 }
740 }
741}
742
744FOutcome FStatusHeaders::TryRecvResponse(FTlsPeer& Peer)
745{
746 FOutcome Outcome = GetDriver().RecvResponse(Peer, &ResponseHeaders);
747 if (!Outcome.IsOk())
748 {
749 return Outcome;
750 }
751
752 enum : uint32 {
753 Flag_Code = 1 << 0,
754 Flag_Length = 1 << 1,
756 };
757 uint32 Flags = 0;
758 for (const FHeaderNg& Header : ResponseHeaders)
759 {
760 if (Flags == Flag_All)
761 {
762 break;
763 }
764
765 FAnsiStringView Key = Header.Key.Get();
766 FAnsiStringView Value = Header.Value.Get();
767
768 if ((Flags ^ Flag_Code) && (Key == ":status"))
769 {
770 StatusCode = uint32(CrudeToInt(Value));
771 Flags |= Flag_Code;
772 }
773 else if ((Flags ^ Flag_Length) && (Key == "content-length"))
774 {
775 ContentLength = CrudeToInt(Value);
777 }
778 }
779
780 if ((Flags & Flag_Code) == 0 || !IsStatusCodeOk(StatusCode))
781 {
782 return FOutcome::Error("Invalid status code", StatusCode);
783 }
784
785 if (IsContentless(StatusCode))
786 {
787 ContentLength = 0;
788 }
789
790 return FOutcome::Ok();
791}
792
793
794
796class FBody
797 : public FStatusHeaders
798{
799public:
800 using FStatusHeaders::FStatusHeaders;
801
802 int64 GetRemaining() const;
803 FOutcome TryRecv(FMutableMemoryView Dest, FTlsPeer& Peer);
804
805private:
806 int64 Remaining = -1;
807};
808
810int64 FBody::GetRemaining() const
811{
812 return Remaining;
813}
814
816FOutcome FBody::TryRecv(FMutableMemoryView Dest, FTlsPeer& Peer)
817{
818 if (!IsChunked())
819 {
820 if (Remaining < 0)
821 {
822 Remaining = GetContentLength();
823 }
824 Dest = Dest.Left(Remaining);
825 }
826
827 FOutcome Outcome = GetDriver().RecvBody(Peer, Dest);
828 if (Outcome.IsError())
829 {
830 return Outcome;
831 }
832
833 Remaining -= Outcome.GetResult();
834 return Outcome;
835}
836
837} // namespace DetailTwo
838
839
840
842class FTransactionTwo
843 : public DetailTwo::FBody
844{
845public:
846 using DetailTwo::FBody::FBody;
847};
848
849
850
852FOutcome HandshakeTwo(FTlsPeer& Peer, void*& PeerData)
853{
854 using namespace DetailTwo;
855
856 if (PeerData == nullptr)
857 {
858 PeerData = new FDriverNg(Peer);
859 }
860
861 auto* Driver = (FDriverNg*)PeerData;
862 return Driver->Handshake(Peer);
863}
864
866FOutcome TickTwo(FTlsPeer& Peer, void* PeerData)
867{
868 using namespace DetailTwo;
869
870 auto* Driver = (FDriverNg*)PeerData;
871 return Driver->GetTransactId(Peer);
872}
873
875void GoAwayTwo(FTlsPeer& Peer, void* PeerData)
876{
877 using namespace DetailTwo;
878
879 auto* Driver = (FDriverNg*)PeerData;
880 if (Driver == nullptr)
881 {
882 return;
883 }
884
885 Driver->GoAway(Peer);
886 delete Driver;
887}
888
889} // namespace UE::IoStore::HTTP
890
891#else // IAS_HTTP_WITH_TWO
892
894namespace UE::IoStore::HTTP {
895
897{
898public:
899 void Begin(...) {}
900 void AddHeader(...) {}
901 FTransactId End(...) { return 0; }
904 bool IsKeepAlive() const { return false; }
905 uint32 GetStatusCode() const { return 0; }
906 FAnsiStringView GetStatusMessage() const { return {}; }
907 int64 GetContentLength() const { return -1; }
908 bool IsChunked() const { return false; }
909 int64 GetRemaining() const { return -1; }
912};
915void GoAwayTwo(FTlsPeer&, void*) {}
916
917} // namespace UE::IoStore::HTTP
918
919#endif // IAS_HTTP_WITH_TWO
#define check(expr)
Definition AssertionMacros.h:314
#define UE_NONCOPYABLE(TypeName)
Definition CoreMiscDefines.h:457
FPlatformTypes::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
TMemoryView< void > FMutableMemoryView
Definition MemoryFwd.h:14
@ Num
Definition MetalRHIPrivate.h:234
@ Char
Character type.
#define ON_SCOPE_EXIT
Definition ScopeExit.h:73
auto GetData(const TStringConversion< Converter, DefaultConversionSize > &Conversion) -> decltype(Conversion.Get())
Definition StringConv.h:802
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint32 Size
Definition VulkanMemory.cpp:4034
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Array.h:670
Definition AndroidPlatformMisc.h:14
constexpr DataType * GetData() const
Definition MemoryView.h:68
constexpr TMemoryView Left(uint64 InSize) const
Definition MemoryView.h:83
constexpr TMemoryView LeftChop(uint64 InSize) const
Definition MemoryView.h:91
DataType * GetDataEnd() const
Definition MemoryView.h:71
constexpr bool IsEmpty() const
Definition MemoryView.h:77
TMemoryView Right(uint64 InSize) const
Definition MemoryView.h:99
TMemoryView Mid(uint64 InOffset, uint64 InSize=TNumericLimits< uint64 >::Max()) const
Definition MemoryView.h:115
constexpr uint64 GetSize() const
Definition MemoryView.h:74
Definition Misc.inl:73
static FOutcome None()
Definition Misc.inl:80
Definition Peer.inl:423
Definition TransactionTwo.inl:897
void AddHeader(...)
Definition TransactionTwo.inl:900
void Begin(...)
Definition TransactionTwo.inl:899
FTransactId End(...)
Definition TransactionTwo.inl:901
int64 GetRemaining() const
Definition TransactionTwo.inl:909
FOutcome TrySendRequest(FTlsPeer &)
Definition TransactionTwo.inl:902
int64 GetContentLength() const
Definition TransactionTwo.inl:907
uint32 GetStatusCode() const
Definition TransactionTwo.inl:905
FOutcome TryRecv(FMutableMemoryView, FTlsPeer &)
Definition TransactionTwo.inl:911
void ReadHeaders(FResponse::FHeaderSink) const
Definition TransactionTwo.inl:910
bool IsChunked() const
Definition TransactionTwo.inl:908
bool IsKeepAlive() const
Definition TransactionTwo.inl:904
FAnsiStringView GetStatusMessage() const
Definition TransactionTwo.inl:906
FOutcome TryRecvResponse(FTlsPeer &)
Definition TransactionTwo.inl:903
CORE_API UE_STRING_CLASS Mid(int32 Start, int32 Count) const &
Definition String.cpp.inl:863
@ IgnoreCase
Definition CString.h:26
Definition Client.h:20
bool IsStatusCodeOk(uint32 StatusCode)
Definition TransactionTwo.inl:18
bool IsContentless(uint32 StatusCode)
Definition TransactionTwo.inl:12
FOutcome TickTwo(FTlsPeer &, void *)
Definition TransactionTwo.inl:914
uint32 FTransactId
Definition TransactionTwo.inl:9
void GoAwayTwo(FTlsPeer &, void *)
Definition TransactionTwo.inl:915
FOutcome HandshakeTwo(FTlsPeer &, void *&)
Definition TransactionTwo.inl:913
Definition Stack.h:114
static FORCENOINLINE CORE_API void Free(void *Original)
Definition UnrealMemory.cpp:685