Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
Http2Connection.cs
Go to the documentation of this file.
6using System.IO;
12using System.Text;
17
18namespace System.Net.Http;
19
20internal sealed class Http2Connection : HttpConnectionBase
21{
22 internal enum KeepAliveState
23 {
24 None,
26 }
27
44
45 private abstract class WriteQueueEntry : TaskCompletionSource
46 {
48
49 public int WriteBytes { get; }
50
60
62 {
64 return !base.Task.IsCanceled;
65 }
66
67 public abstract bool InvokeWriteAction(Memory<byte> writeBuffer);
68 }
69
70 private sealed class WriteQueueEntry<T> : WriteQueueEntry
71 {
72 private readonly T _state;
73
74 private readonly Func<T, Memory<byte>, bool> _writeAction;
75
82
83 public override bool InvokeWriteAction(Memory<byte> writeBuffer)
84 {
85 return _writeAction(_state, writeBuffer);
86 }
87 }
88
89 private enum FrameType : byte
90 {
91 Data = 0,
92 Headers = 1,
93 Priority = 2,
94 RstStream = 3,
95 Settings = 4,
96 PushPromise = 5,
97 Ping = 6,
98 GoAway = 7,
99 WindowUpdate = 8,
100 Continuation = 9,
101 AltSvc = 10,
102 Last = 10
103 }
104
105 private readonly struct FrameHeader
106 {
107 public readonly int PayloadLength;
108
109 public readonly FrameType Type;
110
111 public readonly FrameFlags Flags;
112
113 public readonly int StreamId;
114
115 public bool PaddedFlag => (Flags & FrameFlags.Padded) != 0;
116
117 public bool AckFlag => (Flags & FrameFlags.EndStream) != 0;
118
119 public bool EndHeadersFlag => (Flags & FrameFlags.EndHeaders) != 0;
120
121 public bool EndStreamFlag => (Flags & FrameFlags.EndStream) != 0;
122
123 public bool PriorityFlag => (Flags & FrameFlags.Priority) != 0;
124
126 {
128 Type = type;
129 Flags = flags;
131 }
132
134 {
135 FrameFlags flags = (FrameFlags)buffer[4];
136 int payloadLength = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
139 return new FrameHeader(payloadLength, type, flags, streamId);
140 }
141
143 {
145 destination[4] = (byte)flags;
146 destination[0] = (byte)((payloadLength & 0xFF0000) >> 16);
147 destination[1] = (byte)((payloadLength & 0xFF00) >> 8);
148 destination[2] = (byte)((uint)payloadLength & 0xFFu);
149 destination[3] = (byte)type;
150 }
151
152 public override string ToString()
153 {
154 return $"StreamId={StreamId}; Type={Type}; Flags={Flags}; PayloadLength={PayloadLength}";
155 }
156 }
157
158 [Flags]
159 private enum FrameFlags : byte
160 {
161 None = 0,
162 EndStream = 1,
163 Ack = 1,
164 EndHeaders = 4,
165 Padded = 8,
166 Priority = 0x20,
167 ValidBits = 0x2D
168 }
169
170 private enum SettingId : ushort
171 {
172 HeaderTableSize = 1,
178 }
179
181 {
192
193 private enum StreamCompletionState : byte
194 {
196 Completed,
197 Failed
198 }
199
200 private sealed class Http2ReadStream : HttpBaseStream
201 {
203
205
206 public override bool CanRead => _http2Stream != null;
207
208 public override bool CanWrite => false;
209
215
217 {
218 if (System.Net.NetEventSource.Log.IsEnabled())
219 {
220 _http2Stream?.Trace("", "Finalize");
221 }
222 try
223 {
224 Dispose(disposing: false);
225 }
226 catch (Exception value)
227 {
228 if (System.Net.NetEventSource.Log.IsEnabled())
229 {
230 _http2Stream?.Trace($"Error: {value}", "Finalize");
231 }
232 }
233 }
234
235 protected override void Dispose(bool disposing)
236 {
238 if (http2Stream != null)
239 {
240 http2Stream.CloseResponseBody();
241 base.Dispose(disposing);
242 }
243 }
244
245 public override int Read(Span<byte> destination)
246 {
247 Http2Stream http2Stream = _http2Stream ?? throw new ObjectDisposedException("Http2ReadStream");
248 return http2Stream.ReadData(destination, _responseMessage);
249 }
250
252 {
254 if (http2Stream == null)
255 {
257 }
258 if (cancellationToken.IsCancellationRequested)
259 {
261 }
263 }
264
271
286
291
296 }
297
298 private sealed class Http2WriteStream : HttpBaseStream
299 {
301
302 public long BytesWritten { get; private set; }
303
304 public override bool CanRead => false;
305
306 public override bool CanWrite => _http2Stream != null;
307
312
313 protected override void Dispose(bool disposing)
314 {
316 if (http2Stream != null)
317 {
318 base.Dispose(disposing);
319 }
320 }
321
322 public override int Read(Span<byte> buffer)
323 {
324 throw new NotSupportedException();
325 }
326
331
337
339 {
340 if (cancellationToken.IsCancellationRequested)
341 {
343 }
345 if (http2Stream == null)
346 {
347 return Task.CompletedTask;
348 }
349 return http2Stream._connection.FlushAsync(cancellationToken);
350 }
351 }
352
354
356
358
360
362
364
366
367 private int _availableCredit;
368
369 private readonly object _creditSyncObject = new object();
370
372
374
376
378
379 private bool _canRetry;
380
382
387
389
390 private bool _hasWaiter;
391
393
395
397
398 private static readonly int[] s_hpackStaticStatusCodeTable = new int[7] { 200, 204, 206, 304, 400, 404, 500 };
399
400 private static readonly (HeaderDescriptor descriptor, byte[] value)[] s_hpackStaticHeaderTable = new(HeaderDescriptor, byte[])[47]
401 {
402 (KnownHeaders.AcceptCharset.Descriptor, Array.Empty<byte>()),
403 (KnownHeaders.AcceptEncoding.Descriptor, Encoding.ASCII.GetBytes("gzip, deflate")),
404 (KnownHeaders.AcceptLanguage.Descriptor, Array.Empty<byte>()),
405 (KnownHeaders.AcceptRanges.Descriptor, Array.Empty<byte>()),
406 (KnownHeaders.Accept.Descriptor, Array.Empty<byte>()),
407 (KnownHeaders.AccessControlAllowOrigin.Descriptor, Array.Empty<byte>()),
408 (KnownHeaders.Age.Descriptor, Array.Empty<byte>()),
409 (KnownHeaders.Allow.Descriptor, Array.Empty<byte>()),
410 (KnownHeaders.Authorization.Descriptor, Array.Empty<byte>()),
411 (KnownHeaders.CacheControl.Descriptor, Array.Empty<byte>()),
412 (KnownHeaders.ContentDisposition.Descriptor, Array.Empty<byte>()),
413 (KnownHeaders.ContentEncoding.Descriptor, Array.Empty<byte>()),
414 (KnownHeaders.ContentLanguage.Descriptor, Array.Empty<byte>()),
415 (KnownHeaders.ContentLength.Descriptor, Array.Empty<byte>()),
416 (KnownHeaders.ContentLocation.Descriptor, Array.Empty<byte>()),
417 (KnownHeaders.ContentRange.Descriptor, Array.Empty<byte>()),
418 (KnownHeaders.ContentType.Descriptor, Array.Empty<byte>()),
419 (KnownHeaders.Cookie.Descriptor, Array.Empty<byte>()),
420 (KnownHeaders.Date.Descriptor, Array.Empty<byte>()),
421 (KnownHeaders.ETag.Descriptor, Array.Empty<byte>()),
422 (KnownHeaders.Expect.Descriptor, Array.Empty<byte>()),
423 (KnownHeaders.Expires.Descriptor, Array.Empty<byte>()),
424 (KnownHeaders.From.Descriptor, Array.Empty<byte>()),
425 (KnownHeaders.Host.Descriptor, Array.Empty<byte>()),
426 (KnownHeaders.IfMatch.Descriptor, Array.Empty<byte>()),
427 (KnownHeaders.IfModifiedSince.Descriptor, Array.Empty<byte>()),
428 (KnownHeaders.IfNoneMatch.Descriptor, Array.Empty<byte>()),
429 (KnownHeaders.IfRange.Descriptor, Array.Empty<byte>()),
430 (KnownHeaders.IfUnmodifiedSince.Descriptor, Array.Empty<byte>()),
431 (KnownHeaders.LastModified.Descriptor, Array.Empty<byte>()),
432 (KnownHeaders.Link.Descriptor, Array.Empty<byte>()),
433 (KnownHeaders.Location.Descriptor, Array.Empty<byte>()),
434 (KnownHeaders.MaxForwards.Descriptor, Array.Empty<byte>()),
435 (KnownHeaders.ProxyAuthenticate.Descriptor, Array.Empty<byte>()),
436 (KnownHeaders.ProxyAuthorization.Descriptor, Array.Empty<byte>()),
437 (KnownHeaders.Range.Descriptor, Array.Empty<byte>()),
438 (KnownHeaders.Referer.Descriptor, Array.Empty<byte>()),
439 (KnownHeaders.Refresh.Descriptor, Array.Empty<byte>()),
440 (KnownHeaders.RetryAfter.Descriptor, Array.Empty<byte>()),
441 (KnownHeaders.Server.Descriptor, Array.Empty<byte>()),
442 (KnownHeaders.SetCookie.Descriptor, Array.Empty<byte>()),
443 (KnownHeaders.StrictTransportSecurity.Descriptor, Array.Empty<byte>()),
444 (KnownHeaders.TransferEncoding.Descriptor, Array.Empty<byte>()),
445 (KnownHeaders.UserAgent.Descriptor, Array.Empty<byte>()),
446 (KnownHeaders.Vary.Descriptor, Array.Empty<byte>()),
447 (KnownHeaders.Via.Descriptor, Array.Empty<byte>()),
448 (KnownHeaders.WWWAuthenticate.Descriptor, Array.Empty<byte>())
449 };
450
451 private static ReadOnlySpan<byte> StatusHeaderName => ":status"u8;
452
453 private object SyncObject => this;
454
455 public int StreamId { get; private set; }
456
458
460
462
464 {
466 _connection = connection;
471 _windowManager = new Http2StreamWindowManager(connection, this);
472 _headerBudgetRemaining = connection._pool.Settings._maxResponseHeadersLength * 1024;
473 if (_request.Content == null)
474 {
476 }
477 else
478 {
481 {
482 _expect100ContinueWaiter = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
483 }
484 }
486 {
488 RequestMessage = _request,
489 Content = new HttpConnectionResponseContent()
490 };
491 }
492
494 {
497 if (System.Net.NetEventSource.Log.IsEnabled())
498 {
499 Trace($"{_request}, {"initialWindowSize"}={initialWindowSize}", "Initialize");
500 }
501 }
502
509
511 {
512 if (_request.Content == null)
513 {
514 return;
515 }
516 if (System.Net.NetEventSource.Log.IsEnabled())
517 {
518 Trace($"{_request.Content}", "SendRequestBodyAsync");
519 }
521 try
522 {
523 bool flag = true;
524 if (_expect100ContinueWaiter != null)
525 {
528 }
529 if (flag)
530 {
532 if (HttpTelemetry.Log.IsEnabled())
533 {
534 HttpTelemetry.Log.RequestContentStart();
535 }
537 if (valueTask.IsCompleted)
538 {
539 valueTask.GetAwaiter().GetResult();
540 }
541 else
542 {
544 {
546 }
547 await valueTask.ConfigureAwait(continueOnCapturedContext: false);
548 }
549 if (HttpTelemetry.Log.IsEnabled())
550 {
551 HttpTelemetry.Log.RequestContentStop(writeStream.BytesWritten);
552 }
553 }
554 if (System.Net.NetEventSource.Log.IsEnabled())
555 {
556 Trace("Finished sending request body.", "SendRequestBodyAsync");
557 }
558 }
559 catch (Exception value)
560 {
561 if (System.Net.NetEventSource.Log.IsEnabled())
562 {
563 Trace($"Failed to send request body: {value}", "SendRequestBodyAsync");
564 }
565 bool flag2;
567 {
569 {
571 Complete();
572 return;
573 }
575 (flag2, _) = tuple;
576 _ = tuple.sendReset;
578 SendReset();
579 Complete();
580 }
581 if (flag2)
582 {
583 _waitSource.SetResult(result: true);
584 }
585 throw;
586 }
587 finally
588 {
589 linkedRegistration.Dispose();
590 }
591 bool flag3 = false;
593 {
595 bool flag4 = false;
597 {
599 flag4 = true;
600 }
601 if (flag3)
602 {
603 SendReset();
604 }
605 else
606 {
608 }
609 if (flag4)
610 {
611 Complete();
612 }
613 }
614 }
615
617 {
618 if (System.Net.NetEventSource.Log.IsEnabled())
619 {
620 Trace("Waiting to send request body content for 100-Continue.", "WaitFor100ContinueAsync");
621 }
623 using (cancellationToken.UnsafeRegister(delegate(object s)
624 {
625 ((TaskCompletionSource<bool>)s).TrySetResult(result: false);
627 {
629 {
631 if (System.Net.NetEventSource.Log.IsEnabled())
632 {
633 http2Stream.Trace("100-Continue timer expired.", "WaitFor100ContinueAsync");
634 }
635 http2Stream._expect100ContinueWaiter?.TrySetResult(result: true);
637 bool result;
638 try
639 {
640 bool flag = await expect100ContinueWaiter.Task.ConfigureAwait(continueOnCapturedContext: false);
642 result = flag;
643 }
644 finally
645 {
647 if (asyncDisposable != null)
648 {
649 await asyncDisposable.DisposeAsync();
650 }
651 }
652 return result;
653 }
654 }
655
656 private void SendReset()
657 {
658 if (System.Net.NetEventSource.Log.IsEnabled())
659 {
660 Trace($"Stream reset. Request={_requestCompletionState}, Response={_responseCompletionState}.", "SendReset");
661 }
662 if (_resetException == null)
663 {
665 }
666 }
667
668 private void Complete()
669 {
670 if (System.Net.NetEventSource.Log.IsEnabled())
671 {
672 Trace($"Stream complete. Request={_requestCompletionState}, Response={_responseCompletionState}.", "Complete");
673 }
676 {
678 if (creditWaiter != null)
679 {
680 creditWaiter.Dispose();
681 _creditWaiter = null;
682 }
683 }
684 }
685
686 private void Cancel()
687 {
688 if (System.Net.NetEventSource.Log.IsEnabled())
689 {
690 Trace("", "Cancel");
691 }
693 bool flag = false;
694 bool flag2 = false;
696 {
698 {
700 }
701 (flag, flag2) = CancelResponseBody();
702 }
703 cancellationTokenSource?.Cancel();
705 {
706 if (flag2)
707 {
708 SendReset();
709 Complete();
710 }
711 }
712 if (flag)
713 {
714 _waitSource.SetResult(result: true);
715 }
716 }
717
719 {
720 bool item = false;
722 {
725 {
726 item = true;
727 }
728 }
729 _responseBuffer.DiscardAll();
731 bool hasWaiter = _hasWaiter;
732 _hasWaiter = false;
734 }
735
736 public void OnWindowUpdate(int amount)
737 {
739 {
740 checked
741 {
743 }
744 if (_availableCredit > 0 && _creditWaiter != null)
745 {
748 {
749 _availableCredit -= num;
750 }
751 }
752 }
753 }
754
756 {
757 if (index <= 7)
758 {
759 if (System.Net.NetEventSource.Log.IsEnabled())
760 {
761 Trace($"Invalid request pseudo-header ID {index}.", "OnStaticIndexedHeader");
762 }
764 }
765 if (index <= 14)
766 {
769 }
770 else
771 {
772 var (descriptor, array) = s_hpackStaticHeaderTable[index - 15];
773 OnHeader(descriptor, array);
774 }
775 }
776
778 {
779 if (index <= 7)
780 {
781 if (System.Net.NetEventSource.Log.IsEnabled())
782 {
783 Trace($"Invalid request pseudo-header ID {index}.", "OnStaticIndexedHeader");
784 }
786 }
787 if (index <= 14)
788 {
791 }
792 else
793 {
796 }
797 }
798
807
808 private void OnStatus(int statusCode)
809 {
810 if (System.Net.NetEventSource.Log.IsEnabled())
811 {
812 Trace($"Status code is {statusCode}", "OnStatus");
813 }
816 {
818 {
819 return;
820 }
821 if (_responseProtocolState == ResponseProtocolState.ExpectingHeaders)
822 {
823 if (System.Net.NetEventSource.Log.IsEnabled())
824 {
825 Trace("Received extra status header.", "OnStatus");
826 }
828 }
829 if (_responseProtocolState != 0)
830 {
831 if (System.Net.NetEventSource.Log.IsEnabled())
832 {
833 Trace($"Status pseudo-header received in {_responseProtocolState} state.", "OnStatus");
834 }
836 }
837 _response.StatusCode = (HttpStatusCode)statusCode;
838 if (statusCode < 200)
839 {
840 _responseProtocolState = ResponseProtocolState.ExpectingIgnoredHeaders;
842 {
843 if (System.Net.NetEventSource.Log.IsEnabled())
844 {
845 Trace("Received 100-Continue status.", "OnStatus");
846 }
848 }
849 return;
850 }
852 if (_expect100ContinueWaiter != null)
853 {
854 bool result = statusCode < 300;
855 if (System.Net.NetEventSource.Log.IsEnabled())
856 {
857 Trace($"Expecting 100 Continue but received final status {statusCode}.", "OnStatus");
858 }
860 }
861 }
862 }
863
865 {
866 if (System.Net.NetEventSource.Log.IsEnabled())
867 {
868 Trace(descriptor.Name + ": " + Encoding.ASCII.GetString(value), "OnHeader");
869 }
870 AdjustHeaderBudget(descriptor.Name.Length + value.Length);
872 {
874 {
875 return;
876 }
877 if (_responseProtocolState != ResponseProtocolState.ExpectingHeaders && _responseProtocolState != ResponseProtocolState.ExpectingTrailingHeaders)
878 {
879 if (System.Net.NetEventSource.Log.IsEnabled())
880 {
881 Trace("Received header before status.", "OnHeader");
882 }
884 }
886 if (_responseProtocolState == ResponseProtocolState.ExpectingTrailingHeaders)
887 {
888 string headerValue = descriptor.GetHeaderValue(value, valueEncoding);
889 _trailers.TryAddWithoutValidation(((descriptor.HeaderType & HttpHeaderType.Request) == HttpHeaderType.Request) ? descriptor.AsCustomHeader() : descriptor, headerValue);
890 }
891 else if ((descriptor.HeaderType & HttpHeaderType.Content) == HttpHeaderType.Content)
892 {
893 string headerValue2 = descriptor.GetHeaderValue(value, valueEncoding);
895 }
896 else
897 {
900 }
901 }
902 }
903
905 {
906 if (name[0] == 58)
907 {
908 if (!name.SequenceEqual(StatusHeaderName))
909 {
910 if (System.Net.NetEventSource.Log.IsEnabled())
911 {
912 Trace("Invalid response pseudo-header '" + Encoding.ASCII.GetString(name) + "'.", "OnHeader");
913 }
915 }
918 }
919 else
920 {
921 if (!HeaderDescriptor.TryGet(name, out var descriptor))
922 {
924 }
925 OnHeader(descriptor, value);
926 }
927 }
928
929 public void OnHeadersStart()
930 {
932 {
934 {
935 case ResponseProtocolState.ExpectingData:
936 _responseProtocolState = ResponseProtocolState.ExpectingTrailingHeaders;
937 if (_trailers == null)
938 {
940 }
941 break;
942 default:
944 break;
945 case ResponseProtocolState.ExpectingStatus:
946 case ResponseProtocolState.Aborted:
947 break;
948 }
949 }
950 }
951
952 public void OnHeadersComplete(bool endStream)
953 {
954 bool hasWaiter;
956 {
958 {
959 case ResponseProtocolState.Aborted:
960 return;
961 case ResponseProtocolState.ExpectingHeaders:
962 _responseProtocolState = (endStream ? ResponseProtocolState.Complete : ResponseProtocolState.ExpectingData);
963 break;
964 case ResponseProtocolState.ExpectingTrailingHeaders:
965 if (!endStream)
966 {
967 if (System.Net.NetEventSource.Log.IsEnabled())
968 {
969 Trace("Trailing headers received without endStream", "OnHeadersComplete");
970 }
972 }
974 break;
975 case ResponseProtocolState.ExpectingIgnoredHeaders:
976 if (endStream)
977 {
979 }
981 return;
982 default:
984 break;
985 }
986 if (endStream)
987 {
990 {
991 Complete();
992 }
993 }
995 {
997 }
999 _hasWaiter = false;
1000 }
1001 if (hasWaiter)
1002 {
1003 _waitSource.SetResult(result: true);
1004 }
1005 }
1006
1008 {
1009 bool hasWaiter;
1011 {
1012 switch (_responseProtocolState)
1013 {
1014 case ResponseProtocolState.Aborted:
1015 return;
1016 default:
1018 break;
1019 case ResponseProtocolState.ExpectingData:
1020 break;
1021 }
1022 if (_responseBuffer.ActiveMemory.Length + buffer.Length > _windowManager.StreamWindowSize)
1023 {
1025 }
1026 _responseBuffer.EnsureAvailableSpace(buffer.Length);
1027 _responseBuffer.AvailableMemory.CopyFrom(buffer);
1028 _responseBuffer.Commit(buffer.Length);
1029 if (endStream)
1030 {
1034 {
1035 Complete();
1036 }
1037 }
1039 _hasWaiter = false;
1040 }
1041 if (hasWaiter)
1042 {
1043 _waitSource.SetResult(result: true);
1044 }
1045 }
1046
1048 {
1049 if (System.Net.NetEventSource.Log.IsEnabled())
1050 {
1051 Trace($"{"resetException"}={resetException}, {"resetStreamErrorCode"}={resetStreamErrorCode}", "OnReset");
1052 }
1053 bool flag = false;
1056 {
1058 {
1059 return;
1060 }
1061 if (canRetry && _responseProtocolState != 0)
1062 {
1063 canRetry = false;
1064 }
1066 {
1068 {
1069 _requestBodyAbandoned = true;
1071 }
1072 }
1073 else
1074 {
1077 flag = true;
1078 }
1079 }
1080 if (cancellationTokenSource != null)
1081 {
1082 cancellationTokenSource.Cancel();
1083 }
1084 else
1085 {
1086 Cancel();
1087 }
1088 }
1089
1091 {
1093 if (resetException != null)
1094 {
1095 if (_canRetry)
1096 {
1098 }
1100 }
1102 {
1104 }
1105 }
1106
1108 {
1110 {
1112 if (_responseProtocolState == ResponseProtocolState.ExpectingHeaders || _responseProtocolState == ResponseProtocolState.ExpectingIgnoredHeaders || _responseProtocolState == ResponseProtocolState.ExpectingStatus)
1113 {
1114 _hasWaiter = true;
1116 return (wait: true, isEmptyResponse: false);
1117 }
1118 if (_responseProtocolState == ResponseProtocolState.ExpectingData || _responseProtocolState == ResponseProtocolState.ExpectingTrailingHeaders)
1119 {
1120 return (wait: false, isEmptyResponse: false);
1121 }
1122 return (wait: false, isEmptyResponse: _responseBuffer.IsEmpty);
1123 }
1124 }
1125
1127 {
1128 bool flag2;
1129 try
1130 {
1131 if (HttpTelemetry.Log.IsEnabled())
1132 {
1133 HttpTelemetry.Log.ResponseHeadersStart();
1134 }
1135 bool flag;
1136 (flag, flag2) = TryEnsureHeaders();
1137 if (flag)
1138 {
1141 _ = tuple2.wait;
1142 flag2 = tuple2.isEmptyResponse;
1143 }
1144 if (HttpTelemetry.Log.IsEnabled())
1145 {
1146 HttpTelemetry.Log.ResponseHeadersStop();
1147 }
1148 }
1149 catch
1150 {
1151 Cancel();
1152 throw;
1153 }
1155 if (flag2)
1156 {
1159 }
1160 else
1161 {
1163 }
1165 {
1167 }
1168 }
1169
1171 {
1173 {
1175 if (!_responseBuffer.IsEmpty)
1176 {
1178 int num = Math.Min(buffer.Length, activeMemory.Length);
1179 activeMemory.Slice(0, num).CopyTo(buffer);
1180 _responseBuffer.Discard(num);
1181 return (wait: false, bytesRead: num);
1182 }
1184 {
1185 return (wait: false, bytesRead: 0);
1186 }
1187 _hasWaiter = true;
1189 _waitSource.RunContinuationsAsynchronously = !partOfSyncRead;
1190 return (wait: true, bytesRead: 0);
1191 }
1192 }
1193
1195 {
1196 if (buffer.Length == 0)
1197 {
1198 return 0;
1199 }
1200 int num;
1201 bool flag;
1202 (flag, num) = TryReadFromBuffer(buffer, partOfSyncRead: true);
1203 if (flag)
1204 {
1205 WaitForData();
1206 (flag, num) = TryReadFromBuffer(buffer, partOfSyncRead: true);
1207 }
1208 if (num != 0)
1209 {
1210 _windowManager.AdjustWindow(num, this);
1211 }
1212 else
1213 {
1215 }
1216 return num;
1217 }
1218
1220 {
1221 if (buffer.Length == 0)
1222 {
1223 return 0;
1224 }
1225 var (flag, num) = TryReadFromBuffer(buffer.Span);
1226 if (flag)
1227 {
1229 (bool wait, int bytesRead) tuple2 = TryReadFromBuffer(buffer.Span);
1230 _ = tuple2.wait;
1231 num = tuple2.bytesRead;
1232 }
1233 if (num != 0)
1234 {
1235 _windowManager.AdjustWindow(num, this);
1236 }
1237 else
1238 {
1240 }
1241 return num;
1242 }
1243
1245 {
1246 byte[] array = ArrayPool<byte>.Shared.Rent(bufferSize);
1247 try
1248 {
1249 while (true)
1250 {
1251 int num;
1252 bool flag;
1253 (flag, num) = TryReadFromBuffer(array, partOfSyncRead: true);
1254 if (flag)
1255 {
1256 WaitForData();
1257 (flag, num) = TryReadFromBuffer(array, partOfSyncRead: true);
1258 }
1259 if (num == 0)
1260 {
1261 break;
1262 }
1263 _windowManager.AdjustWindow(num, this);
1264 destination.Write(new ReadOnlySpan<byte>(array, 0, num));
1265 }
1267 }
1268 finally
1269 {
1270 ArrayPool<byte>.Shared.Return(array);
1271 }
1272 }
1273
1275 {
1276 byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
1277 try
1278 {
1279 while (true)
1280 {
1281 var (flag, num) = TryReadFromBuffer(buffer);
1282 if (flag)
1283 {
1286 _ = tuple2.wait;
1287 num = tuple2.bytesRead;
1288 }
1289 if (num == 0)
1290 {
1291 break;
1292 }
1293 _windowManager.AdjustWindow(num, this);
1294 await destination.WriteAsync(new ReadOnlyMemory<byte>(buffer, 0, num), cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
1295 }
1297 }
1298 finally
1299 {
1300 ArrayPool<byte>.Shared.Return(buffer);
1301 }
1302 }
1303
1305 {
1306 if (_trailers != null)
1307 {
1308 responseMessage.StoreReceivedTrailingHeaders(_trailers);
1309 }
1310 }
1311
1313 {
1315 try
1316 {
1317 while (buffer.Length > 0)
1318 {
1319 int num = -1;
1320 bool flush = false;
1322 {
1323 if (_availableCredit > 0)
1324 {
1325 num = Math.Min(buffer.Length, _availableCredit);
1326 _availableCredit -= num;
1327 if (_availableCredit == 0)
1328 {
1329 flush = true;
1330 }
1331 }
1332 else
1333 {
1334 if (_creditWaiter == null)
1335 {
1337 }
1338 else
1339 {
1341 }
1342 _creditWaiter.Amount = buffer.Length;
1343 }
1344 }
1345 if (num == -1)
1346 {
1349 {
1350 if (_availableCredit == 0)
1351 {
1352 flush = true;
1353 }
1354 }
1355 }
1357 (buffer2, buffer) = SplitBuffer(buffer, num);
1359 }
1360 }
1362 {
1364 {
1366 if (resetException != null)
1367 {
1368 if (_canRetry)
1369 {
1371 }
1373 }
1374 }
1375 throw;
1376 }
1377 finally
1378 {
1379 linkedRegistration.Dispose();
1380 }
1381 }
1382
1383 private void CloseResponseBody()
1384 {
1385 bool flag = false;
1387 {
1389 {
1390 flag = true;
1391 }
1392 }
1393 if (!flag)
1394 {
1395 Cancel();
1396 }
1398 {
1399 _responseBuffer.Dispose();
1400 }
1401 }
1402
1410
1412 {
1413 return _waitSource.GetStatus(token);
1414 }
1415
1420
1427
1428 private void WaitForData()
1429 {
1430 new ValueTask(this, _waitSource.Version).AsTask().GetAwaiter().GetResult();
1431 }
1432
1434 {
1436 {
1438 bool hasWaiter;
1439 lock (http2Stream.SyncObject)
1440 {
1441 hasWaiter = http2Stream._hasWaiter;
1442 http2Stream._hasWaiter = false;
1443 }
1444 if (hasWaiter)
1445 {
1447 }
1448 }, this);
1449 return new ValueTask(this, _waitSource.Version);
1450 }
1451
1452 public void Trace(string message, [CallerMemberName] string memberName = null)
1453 {
1455 }
1456 }
1457
1459 {
1460 private static readonly double StopWatchToTimesSpan = 10000000.0 / (double)Stopwatch.Frequency;
1461
1462 private int _deliveredBytes;
1463
1465
1466 private long _lastWindowUpdate;
1467
1469
1471
1473
1475
1477
1479 {
1480 HttpConnectionSettings settings = connection._pool.Settings;
1482 _deliveredBytes = 0;
1484 if (System.Net.NetEventSource.Log.IsEnabled())
1485 {
1486 stream.Trace($"[FlowControl] InitialClientStreamWindowSize: {StreamWindowSize}, StreamWindowThreshold: {StreamWindowThreshold}, WindowScaleThresholdMultiplier: {WindowScaleThresholdMultiplier}", ".ctor");
1487 }
1488 }
1489
1490 public void Start()
1491 {
1493 }
1494
1496 {
1497 if (stream.ExpectResponseData)
1498 {
1500 {
1502 }
1503 else
1504 {
1506 }
1507 }
1508 }
1509
1511 {
1514 {
1516 _deliveredBytes = 0;
1517 Http2Connection connection = stream.Connection;
1518 Task task = connection.SendWindowUpdateAsync(stream.StreamId, deliveredBytes);
1519 connection.LogExceptions(task);
1520 }
1521 }
1522
1524 {
1527 {
1528 return;
1529 }
1530 int num = _deliveredBytes;
1532 Http2Connection connection = stream.Connection;
1533 TimeSpan minRtt = connection._rttEstimator.MinRtt;
1535 {
1537 if ((double)_deliveredBytes * (double)minRtt.Ticks > (double)(_streamWindowSize * timeSpan.Ticks) * WindowScaleThresholdMultiplier)
1538 {
1540 num += num2 - _streamWindowSize;
1542 if (System.Net.NetEventSource.Log.IsEnabled())
1543 {
1544 stream.Trace($"[FlowControl] Updated Stream Window. StreamWindowSize: {StreamWindowSize}, StreamWindowThreshold: {StreamWindowThreshold}", "AdjustWindowDynamic");
1545 }
1547 {
1548 stream.Trace($"[FlowControl] StreamWindowSize reached the configured maximum of {MaxStreamWindowSize}.", "AdjustWindowDynamic");
1549 }
1550 }
1551 }
1552 _deliveredBytes = 0;
1553 Task task = connection.SendWindowUpdateAsync(stream.StreamId, num);
1554 connection.LogExceptions(task);
1556 }
1557
1559 {
1560 long ticks = (long)(StopWatchToTimesSpan * (double)stopwatchTicks);
1561 return new TimeSpan(ticks);
1562 }
1563 }
1564
1565 private struct RttEstimator
1566 {
1567 private enum State
1568 {
1569 Disabled,
1570 Init,
1571 Waiting,
1572 PingSent,
1574 }
1575
1576 private static readonly long PingIntervalInTicks = (long)(2.0 * (double)Stopwatch.Frequency);
1577
1578 private State _state;
1579
1581
1582 private long _pingCounter;
1583
1584 private int _initialBurst;
1585
1586 private long _minRtt;
1587
1589
1590 public static RttEstimator Create()
1591 {
1592 RttEstimator result = default(RttEstimator);
1594 result._initialBurst = 4;
1595 return result;
1596 }
1597
1599 {
1600 if (_state != 0)
1601 {
1603 }
1604 }
1605
1607 {
1608 if (_state != 0)
1609 {
1610 RefreshRtt(connection);
1611 _state = State.Waiting;
1612 }
1613 }
1614
1616 {
1617 if (_state != State.Waiting)
1618 {
1619 return;
1620 }
1622 bool flag = _initialBurst > 0;
1624 {
1625 if (flag)
1626 {
1627 _initialBurst--;
1628 }
1629 _pingCounter--;
1630 if (System.Net.NetEventSource.Log.IsEnabled())
1631 {
1632 connection.Trace($"[FlowControl] Sending RTT PING with payload {_pingCounter}", "OnDataOrHeadersReceived");
1633 }
1634 connection.LogExceptions(connection.SendPingAsync(_pingCounter));
1636 _state = State.PingSent;
1637 }
1638 }
1639
1640 internal void OnPingAckReceived(long payload, Http2Connection connection)
1641 {
1642 if (_state != State.PingSent && _state != State.TerminatingMayReceivePingAck)
1643 {
1644 if (System.Net.NetEventSource.Log.IsEnabled())
1645 {
1646 connection.Trace($"[FlowControl] Unexpected PING ACK in state {_state}", "OnPingAckReceived");
1647 }
1649 }
1650 if (_state == State.TerminatingMayReceivePingAck)
1651 {
1652 _state = State.Disabled;
1653 return;
1654 }
1655 if (_pingCounter != payload)
1656 {
1657 if (System.Net.NetEventSource.Log.IsEnabled())
1658 {
1659 connection.Trace($"[FlowControl] Unexpected RTT PING ACK payload {payload}, should be {_pingCounter}.", "OnPingAckReceived");
1660 }
1662 }
1663 RefreshRtt(connection);
1664 _state = State.Waiting;
1665 }
1666
1667 internal void OnGoAwayReceived()
1668 {
1669 if (_state == State.PingSent)
1670 {
1671 _state = State.TerminatingMayReceivePingAck;
1672 }
1673 else
1674 {
1675 _state = State.Disabled;
1676 }
1677 }
1678
1679 private void RefreshRtt(Http2Connection connection)
1680 {
1682 long val = ((_minRtt == 0L) ? long.MaxValue : _minRtt);
1683 long value = Math.Min(val, TimeSpan.FromSeconds((double)num / (double)Stopwatch.Frequency).Ticks);
1685 if (System.Net.NetEventSource.Log.IsEnabled())
1686 {
1687 connection.Trace($"[FlowControl] Updated MinRtt: {MinRtt.TotalMilliseconds} ms", "RefreshRtt");
1688 }
1689 }
1690 }
1691
1692 private readonly HttpConnectionPool _pool;
1693
1694 private readonly Stream _stream;
1695
1697
1699
1700 [ThreadStatic]
1701 private static string[] t_headerValues;
1702
1703 private readonly HPackDecoder _hpackDecoder;
1704
1706
1708
1710
1711 private int _nextStream;
1712
1714
1716
1718
1720
1722
1723 private uint _streamsInUse;
1724
1726
1728
1730
1731 private bool _shutdown;
1732
1734
1736
1737 private bool _disposed;
1738
1740
1741 private static readonly byte[] s_http2ConnectionPreface = Encoding.ASCII.GetBytes("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n");
1742
1744 {
1745 SingleReader = true
1746 };
1747
1748 private readonly long _keepAlivePingDelay;
1749
1750 private readonly long _keepAlivePingTimeout;
1751
1753
1755
1757
1759
1761
1762 private object SyncObject => _httpStreams;
1763
1765 {
1766 _pool = pool;
1767 _stream = stream;
1770 _hpackDecoder = new HPackDecoder(4096, pool.Settings._maxResponseHeadersLength * 1024);
1772 _connectionWindow = new CreditManager(this, "_connectionWindow", 65535);
1775 _nextStream = 1;
1778 _streamsInUse = 0u;
1783 _nextPingRequestTimestamp = Environment.TickCount64 + _keepAlivePingDelay;
1785 if (HttpTelemetry.Log.IsEnabled())
1786 {
1787 HttpTelemetry.Log.Http20ConnectionEstablished();
1789 }
1790 if (System.Net.NetEventSource.Log.IsEnabled())
1791 {
1793 }
1794 static long TimeSpanToMs(TimeSpan value)
1795 {
1796 double totalMilliseconds = value.TotalMilliseconds;
1797 return (long)((totalMilliseconds > 2147483647.0) ? 2147483647.0 : totalMilliseconds);
1798 }
1799 }
1800
1802 {
1803 Dispose();
1804 }
1805
1807 {
1808 try
1809 {
1810 _outgoingBuffer.EnsureAvailableSpace(s_http2ConnectionPreface.Length + 9 + 6 + 9 + 4);
1811 s_http2ConnectionPreface.AsSpan().CopyTo(_outgoingBuffer.AvailableSpan);
1813 FrameHeader.WriteTo(_outgoingBuffer.AvailableSpan, 12, FrameType.Settings, FrameFlags.None, 0);
1814 _outgoingBuffer.Commit(9);
1816 _outgoingBuffer.Commit(2);
1818 _outgoingBuffer.Commit(4);
1820 _outgoingBuffer.Commit(2);
1822 _outgoingBuffer.Commit(4);
1823 uint value = 67043329u;
1824 if (System.Net.NetEventSource.Log.IsEnabled())
1825 {
1826 Trace($"Initial connection-level WINDOW_UPDATE, windowUpdateAmount={value}", "SetupAsync");
1827 }
1828 FrameHeader.WriteTo(_outgoingBuffer.AvailableSpan, 4, FrameType.WindowUpdate, FrameFlags.None, 0);
1829 _outgoingBuffer.Commit(9);
1831 _outgoingBuffer.Commit(4);
1834 _outgoingBuffer.Discard(_outgoingBuffer.ActiveLength);
1835 _expectingSettingsAck = true;
1836 }
1838 {
1839 Dispose();
1841 }
1844 }
1845
1847 {
1849 {
1850 if (_disposed)
1851 {
1852 throw new ObjectDisposedException("Http2Connection");
1853 }
1854 if (_shutdown)
1855 {
1856 return default(ValueTask);
1857 }
1858 if (_shutdownWaiter == null)
1859 {
1860 _shutdownWaiter = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
1861 }
1862 return new ValueTask(_shutdownWaiter.Task);
1863 }
1864 }
1865
1866 private void Shutdown()
1867 {
1868 if (System.Net.NetEventSource.Log.IsEnabled())
1869 {
1870 Trace($"{"_shutdown"}={_shutdown}, {"_abortException"}={_abortException}", "Shutdown");
1871 }
1872 SignalAvailableStreamsWaiter(result: false);
1874 _shutdown = true;
1875 }
1876
1878 {
1879 if (System.Net.NetEventSource.Log.IsEnabled())
1880 {
1881 Trace($"{"_shutdownWaiter"}?={_shutdownWaiter != null}", "SignalShutdownWaiter");
1882 }
1883 if (_shutdownWaiter != null)
1884 {
1886 _shutdownWaiter = null;
1887 }
1888 }
1889
1890 public bool TryReserveStream()
1891 {
1893 {
1894 if (_disposed)
1895 {
1896 throw new ObjectDisposedException("Http2Connection");
1897 }
1898 if (_shutdown)
1899 {
1900 return false;
1901 }
1903 {
1904 _streamsInUse++;
1905 return true;
1906 }
1907 }
1908 return false;
1909 }
1910
1911 public void ReleaseStream()
1912 {
1914 {
1915 if (System.Net.NetEventSource.Log.IsEnabled())
1916 {
1917 Trace($"{"_streamsInUse"}={_streamsInUse}", "ReleaseStream");
1918 }
1919 _streamsInUse--;
1921 {
1922 SignalAvailableStreamsWaiter(result: true);
1923 }
1924 if (_streamsInUse == 0)
1925 {
1927 if (_disposed)
1928 {
1929 FinalTeardown();
1930 }
1931 }
1932 }
1933 }
1934
1936 {
1938 {
1939 if (_disposed)
1940 {
1941 throw new ObjectDisposedException("Http2Connection");
1942 }
1943 if (_shutdown)
1944 {
1945 return ValueTask.FromResult(result: false);
1946 }
1948 {
1949 return ValueTask.FromResult(result: true);
1950 }
1951 _availableStreamsWaiter = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
1953 }
1954 }
1955
1956 private void SignalAvailableStreamsWaiter(bool result)
1957 {
1958 if (System.Net.NetEventSource.Log.IsEnabled())
1959 {
1960 Trace($"{"result"}={result}, {"_availableStreamsWaiter"}?={_availableStreamsWaiter != null}", "SignalAvailableStreamsWaiter");
1961 }
1962 if (_availableStreamsWaiter != null)
1963 {
1966 }
1967 }
1968
1970 {
1971 if (System.Net.NetEventSource.Log.IsEnabled())
1972 {
1973 Trace($"{"ActiveLength"}={_outgoingBuffer.ActiveLength}", "FlushOutgoingBytesAsync");
1974 }
1975 if (_outgoingBuffer.ActiveLength > 0)
1976 {
1977 try
1978 {
1980 }
1982 {
1984 }
1986 _outgoingBuffer.Discard(_outgoingBuffer.ActiveLength);
1987 }
1988 }
1989
1991 {
1992 if (System.Net.NetEventSource.Log.IsEnabled())
1993 {
1994 Trace($"{"initialFrame"}={initialFrame}", "ReadFrameAsync");
1995 }
1996 if (_incomingBuffer.ActiveLength < 9)
1997 {
1998 _incomingBuffer.EnsureAvailableSpace(9 - _incomingBuffer.ActiveLength);
1999 do
2000 {
2002 _incomingBuffer.Commit(num);
2003 if (num == 0)
2004 {
2005 if (_incomingBuffer.ActiveLength == 0)
2006 {
2008 }
2009 else
2010 {
2012 }
2013 }
2014 }
2015 while (_incomingBuffer.ActiveLength < 9);
2016 }
2018 if (frameHeader.PayloadLength > 16384)
2019 {
2020 if (initialFrame && System.Net.NetEventSource.Log.IsEnabled())
2021 {
2022 string @string = Encoding.ASCII.GetString(_incomingBuffer.ActiveSpan.Slice(0, Math.Min(20, _incomingBuffer.ActiveLength)));
2023 Trace("HTTP/2 handshake failed. Server returned " + @string, "ReadFrameAsync");
2024 }
2025 _incomingBuffer.Discard(9);
2027 }
2028 _incomingBuffer.Discard(9);
2029 if (_incomingBuffer.ActiveLength < frameHeader.PayloadLength)
2030 {
2031 _incomingBuffer.EnsureAvailableSpace(frameHeader.PayloadLength - _incomingBuffer.ActiveLength);
2032 do
2033 {
2035 _incomingBuffer.Commit(num2);
2036 if (num2 == 0)
2037 {
2038 ThrowPrematureEOF(frameHeader.PayloadLength);
2039 }
2040 }
2041 while (_incomingBuffer.ActiveLength < frameHeader.PayloadLength);
2042 }
2043 return frameHeader;
2044 static void ThrowMissingFrame()
2045 {
2047 }
2049 {
2051 }
2052 }
2053
2055 {
2056 _ = 3;
2057 try
2058 {
2059 try
2060 {
2062 if (frameHeader.Type != FrameType.Settings || frameHeader.AckFlag)
2063 {
2065 }
2066 if (System.Net.NetEventSource.Log.IsEnabled())
2067 {
2068 Trace($"Frame 0: {frameHeader}.", "ProcessIncomingFramesAsync");
2069 }
2071 }
2073 {
2075 }
2076 long frameNum = 1L;
2077 while (true)
2078 {
2079 if (_incomingBuffer.ActiveLength < 9)
2080 {
2081 _incomingBuffer.EnsureAvailableSpace(9 - _incomingBuffer.ActiveLength);
2082 int num;
2083 do
2084 {
2086 _incomingBuffer.Commit(num);
2087 }
2088 while (num != 0 && _incomingBuffer.ActiveLength < 9);
2089 }
2091 if (System.Net.NetEventSource.Log.IsEnabled())
2092 {
2093 Trace($"Frame {frameNum}: {frameHeader}.", "ProcessIncomingFramesAsync");
2094 }
2096 switch (frameHeader.Type)
2097 {
2098 case FrameType.Headers:
2100 break;
2101 case FrameType.Data:
2103 break;
2104 case FrameType.Settings:
2106 break;
2107 case FrameType.Priority:
2109 break;
2110 case FrameType.Ping:
2112 break;
2113 case FrameType.WindowUpdate:
2115 break;
2116 case FrameType.RstStream:
2118 break;
2119 case FrameType.GoAway:
2121 break;
2122 case FrameType.AltSvc:
2124 break;
2125 default:
2127 break;
2128 }
2129 frameNum++;
2130 }
2131 }
2132 catch (Exception ex)
2133 {
2134 if (System.Net.NetEventSource.Log.IsEnabled())
2135 {
2136 Trace("ProcessIncomingFramesAsync: " + ex.Message, "ProcessIncomingFramesAsync");
2137 }
2138 Abort(ex);
2139 }
2140 }
2141
2143 {
2145 {
2147 }
2149 {
2151 {
2152 return null;
2153 }
2154 return value;
2155 }
2156 }
2157
2159 {
2160 if (System.Net.NetEventSource.Log.IsEnabled())
2161 {
2162 Trace($"{frameHeader}", "ProcessHeadersFrame");
2163 }
2164 bool endStream = frameHeader.EndStreamFlag;
2165 int streamId = frameHeader.StreamId;
2168 if (http2Stream != null)
2169 {
2170 http2Stream.OnHeadersStart();
2173 }
2174 else
2175 {
2177 }
2178 _hpackDecoder.Decode(GetFrameData(_incomingBuffer.ActiveSpan.Slice(0, frameHeader.PayloadLength), frameHeader.PaddedFlag, frameHeader.PriorityFlag), frameHeader.EndHeadersFlag, headersHandler);
2179 _incomingBuffer.Discard(frameHeader.PayloadLength);
2180 while (!frameHeader.EndHeadersFlag)
2181 {
2182 frameHeader = await ReadFrameAsync().ConfigureAwait(continueOnCapturedContext: false);
2183 if (frameHeader.Type != FrameType.Continuation || frameHeader.StreamId != streamId)
2184 {
2186 }
2187 _hpackDecoder.Decode(_incomingBuffer.ActiveSpan.Slice(0, frameHeader.PayloadLength), frameHeader.EndHeadersFlag, headersHandler);
2188 _incomingBuffer.Discard(frameHeader.PayloadLength);
2189 }
2191 http2Stream?.OnHeadersComplete(endStream);
2192 }
2193
2195 {
2196 if (hasPad)
2197 {
2198 if (frameData.Length == 0)
2199 {
2201 }
2202 int num = frameData[0];
2203 frameData = frameData.Slice(1);
2204 if (frameData.Length < num)
2205 {
2207 }
2208 frameData = frameData.Slice(0, frameData.Length - num);
2209 }
2210 if (hasPriority)
2211 {
2212 if (frameData.Length < 5)
2213 {
2215 }
2216 frameData = frameData.Slice(5);
2217 }
2218 return frameData;
2219 }
2220
2222 {
2223 if (System.Net.NetEventSource.Log.IsEnabled())
2224 {
2225 Trace($"{frameHeader}", "ProcessAltSvcFrame");
2226 }
2227 ReadOnlySpan<byte> readOnlySpan = _incomingBuffer.ActiveSpan.Slice(0, frameHeader.PayloadLength);
2229 {
2230 readOnlySpan = readOnlySpan.Slice(2);
2231 if ((frameHeader.StreamId != 0 && value == 0) || (frameHeader.StreamId == 0 && readOnlySpan.Length >= value && readOnlySpan.Slice(0, value).SequenceEqual(_pool.Http2AltSvcOriginUri)))
2232 {
2234 string @string = Encoding.ASCII.GetString(readOnlySpan);
2235 _pool.HandleAltSvc(new string[1] { @string }, null);
2236 }
2237 }
2238 _incomingBuffer.Discard(frameHeader.PayloadLength);
2239 }
2240
2242 {
2244 ReadOnlySpan<byte> frameData = GetFrameData(_incomingBuffer.ActiveSpan.Slice(0, frameHeader.PayloadLength), frameHeader.PaddedFlag, hasPriority: false);
2245 if (stream != null)
2246 {
2247 bool endStreamFlag = frameHeader.EndStreamFlag;
2248 stream.OnResponseData(frameData, endStreamFlag);
2249 if (!endStreamFlag && frameData.Length > 0)
2250 {
2252 }
2253 }
2254 if (frameData.Length > 0)
2255 {
2256 ExtendWindow(frameData.Length);
2257 }
2258 _incomingBuffer.Discard(frameHeader.PayloadLength);
2259 }
2260
2262 {
2263 if (frameHeader.StreamId != 0)
2264 {
2266 }
2267 if (frameHeader.AckFlag)
2268 {
2269 if (frameHeader.PayloadLength != 0)
2270 {
2272 }
2274 {
2276 }
2277 _expectingSettingsAck = false;
2279 return;
2280 }
2281 if (frameHeader.PayloadLength % 6 != 0)
2282 {
2284 }
2285 ReadOnlySpan<byte> source = _incomingBuffer.ActiveSpan.Slice(0, frameHeader.PayloadLength);
2286 bool flag = false;
2287 while (source.Length > 0)
2288 {
2290 source = source.Slice(2);
2292 source = source.Slice(4);
2293 switch ((SettingId)num)
2294 {
2295 case SettingId.MaxConcurrentStreams:
2297 flag = true;
2298 break;
2299 case SettingId.InitialWindowSize:
2300 if (num2 > int.MaxValue)
2301 {
2303 }
2305 break;
2306 case SettingId.MaxFrameSize:
2307 if (num2 < 16384 || num2 > 16777215)
2308 {
2310 }
2311 break;
2312 }
2313 }
2314 if (initialFrame && !flag)
2315 {
2316 ChangeMaxConcurrentStreams(2147483647u);
2317 }
2318 _incomingBuffer.Discard(frameHeader.PayloadLength);
2320 }
2321
2323 {
2325 {
2326 if (System.Net.NetEventSource.Log.IsEnabled())
2327 {
2328 Trace($"{"newValue"}={newValue}, {"_streamsInUse"}={_streamsInUse}, {"_availableStreamsWaiter"}?={_availableStreamsWaiter != null}", "ChangeMaxConcurrentStreams");
2329 }
2332 {
2333 SignalAvailableStreamsWaiter(result: true);
2334 }
2335 }
2336 }
2337
2339 {
2340 if (System.Net.NetEventSource.Log.IsEnabled())
2341 {
2342 Trace($"{"newSize"}={newSize}", "ChangeInitialWindowSize");
2343 }
2345 {
2349 {
2350 httpStream.Value.OnWindowUpdate(amount);
2351 }
2352 }
2353 }
2354
2356 {
2357 if (frameHeader.StreamId == 0 || frameHeader.PayloadLength != 5)
2358 {
2360 }
2361 _incomingBuffer.Discard(frameHeader.PayloadLength);
2362 }
2363
2365 {
2366 if (frameHeader.StreamId != 0)
2367 {
2369 }
2370 if (frameHeader.PayloadLength != 8)
2371 {
2373 }
2374 ReadOnlySpan<byte> source = _incomingBuffer.ActiveSpan.Slice(0, 8);
2376 if (System.Net.NetEventSource.Log.IsEnabled())
2377 {
2378 Trace($"Received PING frame, content:{num} ack: {frameHeader.AckFlag}", "ProcessPingFrame");
2379 }
2380 if (frameHeader.AckFlag)
2381 {
2382 ProcessPingAck(num);
2383 }
2384 else
2385 {
2386 LogExceptions(SendPingAsync(num, isAck: true));
2387 }
2388 _incomingBuffer.Discard(frameHeader.PayloadLength);
2389 }
2390
2392 {
2393 if (frameHeader.PayloadLength != 4)
2394 {
2396 }
2397 int num = BinaryPrimitives.ReadInt32BigEndian(_incomingBuffer.ActiveSpan) & 0x7FFFFFFF;
2398 if (System.Net.NetEventSource.Log.IsEnabled())
2399 {
2400 Trace($"{frameHeader}. {"amount"}={num}", "ProcessWindowUpdateFrame");
2401 }
2402 if (num == 0)
2403 {
2405 }
2406 _incomingBuffer.Discard(frameHeader.PayloadLength);
2407 if (frameHeader.StreamId == 0)
2408 {
2410 }
2411 else
2412 {
2413 GetStream(frameHeader.StreamId)?.OnWindowUpdate(num);
2414 }
2415 }
2416
2418 {
2419 if (frameHeader.PayloadLength != 4)
2420 {
2422 }
2423 if (frameHeader.StreamId == 0)
2424 {
2426 }
2428 if (stream == null)
2429 {
2430 _incomingBuffer.Discard(frameHeader.PayloadLength);
2431 return;
2432 }
2434 if (System.Net.NetEventSource.Log.IsEnabled())
2435 {
2436 Trace(frameHeader.StreamId, $"{"protocolError"}={http2ProtocolErrorCode}", "ProcessRstStreamFrame");
2437 }
2438 _incomingBuffer.Discard(frameHeader.PayloadLength);
2440 {
2442 }
2443 else
2444 {
2446 }
2447 }
2448
2450 {
2451 if (frameHeader.PayloadLength < 8)
2452 {
2454 }
2455 if (frameHeader.StreamId != 0)
2456 {
2458 }
2459 int num = (int)(BinaryPrimitives.ReadUInt32BigEndian(_incomingBuffer.ActiveSpan) & 0x7FFFFFFF);
2461 if (System.Net.NetEventSource.Log.IsEnabled())
2462 {
2463 Trace(frameHeader.StreamId, $"{"lastStreamId"}={num}, {"errorCode"}={http2ProtocolErrorCode}", "ProcessGoAwayFrame");
2464 }
2465 _incomingBuffer.Discard(frameHeader.PayloadLength);
2470 {
2471 Shutdown();
2473 {
2474 int key = httpStream.Key;
2475 if (key > num)
2476 {
2477 list.Add(httpStream.Value);
2478 }
2479 }
2480 }
2481 foreach (Http2Stream item in list)
2482 {
2483 item.OnReset(resetException, null, canRetry: true);
2484 }
2485 }
2486
2488 {
2489 return PerformWriteAsync(0, 0, (int _, Memory<byte> __) => true, cancellationToken);
2490 }
2491
2493 {
2495 if (!_writeChannel.Writer.TryWrite(writeQueueEntry))
2496 {
2497 if (_abortException != null)
2498 {
2500 }
2501 return Task.FromException(new ObjectDisposedException("Http2Connection"));
2502 }
2503 return writeQueueEntry.Task;
2504 }
2505
2507 {
2508 _ = 2;
2509 try
2510 {
2511 while (await _writeChannel.Reader.WaitToReadAsync().ConfigureAwait(continueOnCapturedContext: false))
2512 {
2514 while (_writeChannel.Reader.TryRead(out writeEntry))
2515 {
2516 if (_abortException != null)
2517 {
2518 if (writeEntry.TryDisableCancellation())
2519 {
2520 writeEntry.SetException(_abortException);
2521 }
2522 continue;
2523 }
2524 int writeBytes = writeEntry.WriteBytes;
2525 int capacity = _outgoingBuffer.Capacity;
2526 if (capacity >= 32768)
2527 {
2528 int activeLength = _outgoingBuffer.ActiveLength;
2530 {
2532 }
2533 }
2534 if (!writeEntry.TryDisableCancellation())
2535 {
2536 continue;
2537 }
2538 _outgoingBuffer.EnsureAvailableSpace(writeBytes);
2539 try
2540 {
2541 if (System.Net.NetEventSource.Log.IsEnabled())
2542 {
2543 Trace($"{"writeBytes"}={writeBytes}", "ProcessOutgoingFramesAsync");
2544 }
2545 bool flag = writeEntry.InvokeWriteAction(_outgoingBuffer.AvailableMemorySliced(writeBytes));
2546 writeEntry.SetResult();
2549 }
2550 catch (Exception exception)
2551 {
2552 writeEntry.SetException(exception);
2553 }
2554 }
2556 {
2558 }
2559 }
2560 }
2561 catch (Exception value)
2562 {
2563 if (System.Net.NetEventSource.Log.IsEnabled())
2564 {
2565 Trace($"Unexpected exception in {"ProcessOutgoingFramesAsync"}: {value}", "ProcessOutgoingFramesAsync");
2566 }
2567 }
2568 }
2569
2571 {
2572 return PerformWriteAsync(9, this, delegate(Http2Connection thisRef, Memory<byte> writeBuffer)
2573 {
2574 if (System.Net.NetEventSource.Log.IsEnabled())
2575 {
2576 thisRef.Trace("Started writing.", "SendSettingsAckAsync");
2577 }
2578 FrameHeader.WriteTo(writeBuffer.Span, 0, FrameType.Settings, FrameFlags.EndStream, 0);
2579 return true;
2580 });
2581 }
2582
2583 private Task SendPingAsync(long pingContent, bool isAck = false)
2584 {
2585 return PerformWriteAsync(17, (this, pingContent, isAck), delegate((Http2Connection thisRef, long pingContent, bool isAck) state, Memory<byte> writeBuffer)
2586 {
2587 if (System.Net.NetEventSource.Log.IsEnabled())
2588 {
2589 state.thisRef.Trace($"Started writing. {"pingContent"}={state.pingContent}", "SendPingAsync");
2590 }
2591 Span<byte> span = writeBuffer.Span;
2592 FrameHeader.WriteTo(span, 8, FrameType.Ping, state.isAck ? FrameFlags.EndStream : FrameFlags.None, 0);
2593 BinaryPrimitives.WriteInt64BigEndian(span.Slice(9), state.pingContent);
2594 return true;
2595 });
2596 }
2597
2599 {
2601 {
2602 if (System.Net.NetEventSource.Log.IsEnabled())
2603 {
2604 s.thisRef.Trace(s.streamId, $"Started writing. {"errorCode"}={s.errorCode}", "SendRstStreamAsync");
2605 }
2606 Span<byte> span = writeBuffer.Span;
2607 FrameHeader.WriteTo(span, 4, FrameType.RstStream, FrameFlags.None, s.streamId);
2608 BinaryPrimitives.WriteInt32BigEndian(span.Slice(9), (int)s.errorCode);
2609 return true;
2610 });
2611 }
2612
2613 internal void HeartBeat()
2614 {
2615 if (_disposed)
2616 {
2617 return;
2618 }
2619 try
2620 {
2622 }
2623 catch (Exception ex)
2624 {
2625 if (System.Net.NetEventSource.Log.IsEnabled())
2626 {
2627 Trace("HeartBeat: " + ex.Message, "HeartBeat");
2628 }
2629 Abort(ex);
2630 }
2631 }
2632
2634 {
2635 if (buffer.Length <= maxSize)
2636 {
2637 return (first: buffer, rest: Memory<byte>.Empty);
2638 }
2639 return (first: buffer.Slice(0, maxSize), rest: buffer.Slice(maxSize));
2640 }
2641
2643 {
2644 if (System.Net.NetEventSource.Log.IsEnabled())
2645 {
2646 Trace($"{"index"}={index}", "WriteIndexedHeader");
2647 }
2648 int bytesWritten;
2650 {
2651 headerBuffer.EnsureAvailableSpace(headerBuffer.AvailableLength + 1);
2652 }
2653 headerBuffer.Commit(bytesWritten);
2654 }
2655
2657 {
2658 if (System.Net.NetEventSource.Log.IsEnabled())
2659 {
2660 Trace($"{"index"}={index}, {"value"}={value}", "WriteIndexedHeader");
2661 }
2662 int bytesWritten;
2664 {
2665 headerBuffer.EnsureAvailableSpace(headerBuffer.AvailableLength + 1);
2666 }
2667 headerBuffer.Commit(bytesWritten);
2668 }
2669
2671 {
2672 if (System.Net.NetEventSource.Log.IsEnabled())
2673 {
2674 Trace($"{"name"}={name}, {"values"}={string.Join(", ", values.ToArray())}", "WriteLiteralHeader");
2675 }
2676 int bytesWritten;
2678 {
2679 headerBuffer.EnsureAvailableSpace(headerBuffer.AvailableLength + 1);
2680 }
2681 headerBuffer.Commit(bytesWritten);
2682 }
2683
2685 {
2686 if (System.Net.NetEventSource.Log.IsEnabled())
2687 {
2688 Trace("values=" + string.Join(separator, values.ToArray()), "WriteLiteralHeaderValues");
2689 }
2690 int bytesWritten;
2692 {
2693 headerBuffer.EnsureAvailableSpace(headerBuffer.AvailableLength + 1);
2694 }
2695 headerBuffer.Commit(bytesWritten);
2696 }
2697
2699 {
2700 if (System.Net.NetEventSource.Log.IsEnabled())
2701 {
2702 Trace("value=" + value, "WriteLiteralHeaderValue");
2703 }
2704 int bytesWritten;
2706 {
2707 headerBuffer.EnsureAvailableSpace(headerBuffer.AvailableLength + 1);
2708 }
2709 headerBuffer.Commit(bytesWritten);
2710 }
2711
2713 {
2714 if (System.Net.NetEventSource.Log.IsEnabled())
2715 {
2716 Trace($"{"Length"}={bytes.Length}", "WriteBytes");
2717 }
2718 if (bytes.Length > headerBuffer.AvailableLength)
2719 {
2720 headerBuffer.EnsureAvailableSpace(bytes.Length);
2721 }
2722 bytes.CopyTo(headerBuffer.AvailableSpan);
2723 headerBuffer.Commit(bytes.Length);
2724 }
2725
2727 {
2728 if (System.Net.NetEventSource.Log.IsEnabled())
2729 {
2730 Trace("", "WriteHeaderCollection");
2731 }
2732 if (headers.HeaderStore == null)
2733 {
2734 return;
2735 }
2737 foreach (KeyValuePair<HeaderDescriptor, object> item in headers.HeaderStore)
2738 {
2742 KnownHeader knownHeader = item.Key.KnownHeader;
2743 if (knownHeader != null)
2744 {
2746 {
2747 continue;
2748 }
2749 if (item.Key.KnownHeader == KnownHeaders.TE)
2750 {
2752 for (int i = 0; i < readOnlySpan2.Length; i++)
2753 {
2754 string text = readOnlySpan2[i];
2755 if (string.Equals(text, "trailers", StringComparison.OrdinalIgnoreCase))
2756 {
2757 WriteBytes(knownHeader.Http2EncodedName, ref headerBuffer);
2759 break;
2760 }
2761 }
2762 }
2763 else
2764 {
2765 WriteBytes(knownHeader.Http2EncodedName, ref headerBuffer);
2766 string separator = null;
2767 if (readOnlySpan.Length > 1)
2768 {
2769 HttpHeaderParser parser = item.Key.Parser;
2770 separator = ((parser == null || !parser.SupportsMultipleValues) ? ", " : parser.Separator);
2771 }
2773 }
2774 }
2775 else
2776 {
2778 }
2779 }
2780 }
2781
2783 {
2784 if (System.Net.NetEventSource.Log.IsEnabled())
2785 {
2786 Trace("", "WriteHeaders");
2787 }
2788 if (request.HasHeaders && request.Headers.TransferEncodingChunked == true)
2789 {
2790 request.Headers.TransferEncodingChunked = false;
2791 }
2793 if ((object)httpMethod == HttpMethod.Get)
2794 {
2796 }
2797 else if ((object)httpMethod == HttpMethod.Post)
2798 {
2800 }
2801 else
2802 {
2804 }
2806 if (request.HasHeaders && request.Headers.Host != null)
2807 {
2808 WriteIndexedHeader(1, request.Headers.Host, ref headerBuffer);
2809 }
2810 else
2811 {
2813 }
2814 string pathAndQuery = request.RequestUri.PathAndQuery;
2815 if (pathAndQuery == "/")
2816 {
2818 }
2819 else
2820 {
2822 }
2823 if (request.HasHeaders)
2824 {
2826 }
2828 {
2830 if (cookieHeader != string.Empty)
2831 {
2832 WriteBytes(KnownHeaders.Cookie.Http2EncodedName, ref headerBuffer);
2835 }
2836 }
2837 if (request.Content == null)
2838 {
2839 if (httpMethod.MustHaveRequestBody)
2840 {
2843 }
2844 }
2845 else
2846 {
2848 }
2849 }
2850
2852 {
2854 {
2855 if (_nextStream == int.MaxValue)
2856 {
2857 Shutdown();
2858 }
2859 if (_abortException != null)
2860 {
2862 }
2863 if (_shutdown)
2864 {
2866 }
2868 {
2870 }
2872 _nextStream += 2;
2874 }
2875 }
2876
2878 {
2880 try
2881 {
2882 if (HttpTelemetry.Log.IsEnabled())
2883 {
2884 HttpTelemetry.Log.RequestHeadersStart();
2885 }
2886 headerBuffer = new System.Net.ArrayBuffer(4096, usePool: true);
2888 ReadOnlyMemory<byte> item = headerBuffer.ActiveMemory;
2889 int num = (item.Length - 1) / 16384 + 1;
2890 int writeBytes = item.Length + num * 9;
2893 {
2894 if (System.Net.NetEventSource.Log.IsEnabled())
2895 {
2896 s.thisRef.Trace(s.http2Stream.StreamId, $"Started writing. Total header bytes={s.headerBytes.Length}", "SendHeadersAsync");
2897 }
2898 s.thisRef.AddStream(s.http2Stream);
2899 Span<byte> destination = writeBuffer.Span;
2903 FrameFlags frameFlags = ((item3.Length == 0) ? FrameFlags.EndHeaders : FrameFlags.None);
2904 frameFlags |= (s.endStream ? FrameFlags.EndStream : FrameFlags.None);
2905 FrameHeader.WriteTo(destination, item2.Length, FrameType.Headers, frameFlags, s.http2Stream.StreamId);
2906 destination = destination.Slice(9);
2907 item2.Span.CopyTo(destination);
2908 destination = destination.Slice(item2.Length);
2909 if (System.Net.NetEventSource.Log.IsEnabled())
2910 {
2911 s.thisRef.Trace(s.http2Stream.StreamId, $"Wrote HEADERS frame. Length={item2.Length}, flags={frameFlags}", "SendHeadersAsync");
2912 }
2913 while (item3.Length > 0)
2914 {
2916 item2 = tuple2.first;
2917 item3 = tuple2.rest;
2918 frameFlags = ((item3.Length == 0) ? FrameFlags.EndHeaders : FrameFlags.None);
2919 FrameHeader.WriteTo(destination, item2.Length, FrameType.Continuation, frameFlags, s.http2Stream.StreamId);
2920 destination = destination.Slice(9);
2921 item2.Span.CopyTo(destination);
2922 destination = destination.Slice(item2.Length);
2923 if (System.Net.NetEventSource.Log.IsEnabled())
2924 {
2925 s.thisRef.Trace(s.http2Stream.StreamId, $"Wrote CONTINUATION frame. Length={item2.Length}, flags={frameFlags}", "SendHeadersAsync");
2926 }
2927 }
2928 return s.mustFlush || s.endStream;
2929 }, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
2930 if (HttpTelemetry.Log.IsEnabled())
2931 {
2932 HttpTelemetry.Log.RequestHeadersStop();
2933 }
2934 return http2Stream;
2935 }
2936 catch
2937 {
2938 ReleaseStream();
2939 throw;
2940 }
2941 finally
2942 {
2943 headerBuffer.Dispose();
2944 }
2945 }
2946
2948 {
2950 while (remaining.Length > 0)
2951 {
2952 int frameSize = Math.Min(remaining.Length, 16384);
2956 remaining = tuple.Item2;
2957 bool item2 = false;
2958 if (finalFlush && remaining.Length == 0)
2959 {
2960 item2 = true;
2961 }
2963 {
2964 item2 = true;
2965 }
2966 try
2967 {
2969 {
2970 if (System.Net.NetEventSource.Log.IsEnabled())
2971 {
2972 s.thisRef.Trace(s.streamId, $"Started writing. {"Length"}={writeBuffer.Length}", "SendStreamDataAsync");
2973 }
2974 FrameHeader.WriteTo(writeBuffer.Span, s.current.Length, FrameType.Data, FrameFlags.None, s.streamId);
2975 s.current.CopyTo(writeBuffer.Slice(9));
2976 return s.flush;
2977 }, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
2978 }
2979 catch
2980 {
2982 throw;
2983 }
2984 }
2985 }
2986
2988 {
2989 return PerformWriteAsync(9, (this, streamId), delegate((Http2Connection thisRef, int streamId) s, Memory<byte> writeBuffer)
2990 {
2991 if (System.Net.NetEventSource.Log.IsEnabled())
2992 {
2993 s.thisRef.Trace(s.streamId, "Started writing.", "SendEndStreamAsync");
2994 }
2995 FrameHeader.WriteTo(writeBuffer.Span, 0, FrameType.Data, FrameFlags.EndStream, s.streamId);
2996 return true;
2997 });
2998 }
2999
3001 {
3002 return PerformWriteAsync(13, (this, streamId, amount), delegate((Http2Connection thisRef, int streamId, int amount) s, Memory<byte> writeBuffer)
3003 {
3004 if (System.Net.NetEventSource.Log.IsEnabled())
3005 {
3006 s.thisRef.Trace(s.streamId, $"Started writing. {"amount"}={s.amount}", "SendWindowUpdateAsync");
3007 }
3008 Span<byte> span = writeBuffer.Span;
3009 FrameHeader.WriteTo(span, 4, FrameType.WindowUpdate, FrameFlags.None, s.streamId);
3010 BinaryPrimitives.WriteInt32BigEndian(span.Slice(9), s.amount);
3011 return true;
3012 });
3013 }
3014
3015 private void ExtendWindow(int amount)
3016 {
3017 if (System.Net.NetEventSource.Log.IsEnabled())
3018 {
3019 Trace($"{"amount"}={amount}", "ExtendWindow");
3020 }
3023 {
3025 if (_pendingWindowUpdate < 8388608)
3026 {
3027 if (System.Net.NetEventSource.Log.IsEnabled())
3028 {
3029 Trace($"{"_pendingWindowUpdate"} {_pendingWindowUpdate} < {8388608}.", "ExtendWindow");
3030 }
3031 return;
3032 }
3035 }
3037 }
3038
3039 public override long GetIdleTicks(long nowTicks)
3040 {
3042 {
3043 return (_streamsInUse == 0) ? (nowTicks - _idleSinceTickCount) : 0;
3044 }
3045 }
3046
3048 {
3049 if (System.Net.NetEventSource.Log.IsEnabled())
3050 {
3051 Trace($"{"abortException"}=={abortException}", "Abort");
3052 }
3055 {
3056 if (_abortException != null)
3057 {
3058 if (System.Net.NetEventSource.Log.IsEnabled())
3059 {
3060 Trace($"Abort called while already aborting. {"abortException"}={abortException}", "Abort");
3061 }
3062 return;
3063 }
3065 Shutdown();
3067 {
3068 int key = httpStream.Key;
3069 list.Add(httpStream.Value);
3070 }
3071 }
3072 foreach (Http2Stream item in list)
3073 {
3074 item.OnReset(_abortException);
3075 }
3076 }
3077
3078 private void FinalTeardown()
3079 {
3080 if (System.Net.NetEventSource.Log.IsEnabled())
3081 {
3082 Trace("", "FinalTeardown");
3083 }
3084 GC.SuppressFinalize(this);
3085 _stream.Dispose();
3087 _writeChannel.Writer.Complete();
3089 {
3090 HttpTelemetry.Log.Http20ConnectionClosed();
3091 }
3092 }
3093
3094 public override void Dispose()
3095 {
3097 {
3098 if (System.Net.NetEventSource.Log.IsEnabled())
3099 {
3100 Trace($"{"_disposed"}={_disposed}, {"_streamsInUse"}={_streamsInUse}", "Dispose");
3101 }
3102 if (!_disposed)
3103 {
3104 SignalAvailableStreamsWaiter(result: false);
3106 _disposed = true;
3107 if (_streamsInUse == 0)
3108 {
3109 FinalTeardown();
3110 }
3111 }
3112 }
3113 }
3114
3116 {
3117 if (System.Net.NetEventSource.Log.IsEnabled())
3118 {
3119 Trace($"{request}", "SendAsync");
3120 }
3121 try
3122 {
3123 bool mustFlush = request.Content != null && request.HasHeaders && request.Headers.ExpectContinue == true;
3125 bool flag = request.Content != null && request.Content.AllowDuplex;
3126 CancellationToken cancellationToken2 = (flag ? CancellationToken.None : cancellationToken);
3127 Task requestBodyTask = http2Stream.SendRequestBodyAsync(cancellationToken2);
3128 Task responseHeadersTask = http2Stream.ReadResponseHeadersAsync(cancellationToken);
3129 bool flag2 = requestBodyTask.IsCompleted || !flag;
3130 bool flag3 = flag2;
3131 if (!flag3)
3132 {
3134 }
3135 if (flag3 || requestBodyTask.IsCompleted || http2Stream.SendRequestFinished)
3136 {
3137 try
3138 {
3139 await requestBodyTask.ConfigureAwait(continueOnCapturedContext: false);
3140 }
3141 catch (Exception value)
3142 {
3143 if (System.Net.NetEventSource.Log.IsEnabled())
3144 {
3145 Trace($"Sending request content failed: {value}", "SendAsync");
3146 }
3148 throw;
3149 }
3150 }
3151 else
3152 {
3154 }
3156 return http2Stream.GetAndClearResponse();
3157 }
3158 catch (Exception ex)
3159 {
3161 {
3163 }
3164 throw;
3165 }
3166 }
3167
3169 {
3170 if (System.Net.NetEventSource.Log.IsEnabled())
3171 {
3172 Trace(http2Stream.StreamId, "", "RemoveStream");
3173 }
3175 {
3176 if (!_httpStreams.Remove(http2Stream.StreamId))
3177 {
3178 return;
3179 }
3180 }
3181 ReleaseStream();
3182 }
3183
3185 {
3186 _nextPingRequestTimestamp = Environment.TickCount64 + _keepAlivePingDelay;
3187 }
3188
3189 private void ProcessPingAck(long payload)
3190 {
3191 if (payload < 0)
3192 {
3194 return;
3195 }
3196 if (_keepAliveState != KeepAliveState.PingSent)
3197 {
3199 }
3201 {
3203 }
3205 }
3206
3207 private void VerifyKeepAlive()
3208 {
3209 if (_keepAlivePingPolicy == HttpKeepAlivePingPolicy.WithActiveRequests)
3210 {
3212 {
3213 if (_streamsInUse == 0)
3214 {
3215 return;
3216 }
3217 }
3218 }
3219 long tickCount = Environment.TickCount64;
3220 switch (_keepAliveState)
3221 {
3222 case KeepAliveState.None:
3223 if (tickCount > _nextPingRequestTimestamp)
3224 {
3229 }
3230 break;
3231 case KeepAliveState.PingSent:
3232 if (tickCount > _keepAlivePingTimeoutTimestamp)
3233 {
3235 }
3236 break;
3237 }
3238 }
3239
3240 public sealed override string ToString()
3241 {
3242 return $"{"Http2Connection"}({_pool})";
3243 }
3244
3245 public override void Trace(string message, [CallerMemberName] string memberName = null)
3246 {
3247 Trace(0, message, memberName);
3248 }
3249
3250 internal void Trace(int streamId, string message, [CallerMemberName] string memberName = null)
3251 {
3252 System.Net.NetEventSource.Log.HandlerMessage(_pool?.GetHashCode() ?? 0, GetHashCode(), streamId, memberName, message);
3253 }
3254
3256 private static void ThrowRetry(string message, Exception innerException = null)
3257 {
3258 throw new HttpRequestException(message, innerException, RequestRetryType.RetryOnConnectionFailure);
3259 }
3260
3265
3268 {
3270 }
3271
3273 private static void ThrowProtocolError()
3274 {
3276 }
3277
3280 {
3282 }
3283}
static uint ReadUInt32BigEndian(ReadOnlySpan< byte > source)
static int ReadInt32BigEndian(ReadOnlySpan< byte > source)
static void WriteUInt32BigEndian(Span< byte > destination, uint value)
static void WriteUInt16BigEndian(Span< byte > destination, ushort value)
static void WriteInt64BigEndian(Span< byte > destination, long value)
static ushort ReadUInt16BigEndian(ReadOnlySpan< byte > source)
static long ReadInt64BigEndian(ReadOnlySpan< byte > source)
static bool TryReadUInt16BigEndian(ReadOnlySpan< byte > source, out ushort value)
static void WriteInt32BigEndian(Span< byte > destination, int value)
bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
bool ICollection< KeyValuePair< TKey, TValue > >. Remove(KeyValuePair< TKey, TValue > keyValuePair)
void CopyTo(KeyValuePair< TKey, TValue >[] array, int index)
void Add(TKey key, TValue value)
static readonly long Frequency
Definition Stopwatch.cs:13
static long TickCount64
static void SuppressFinalize(object obj)
Definition GC.cs:202
Definition GC.cs:8
static void ValidateCopyToArguments(Stream destination, int bufferSize)
Definition Stream.cs:1060
Task WriteAsync(byte[] buffer, int offset, int count)
Definition Stream.cs:914
void Dispose()
Definition Stream.cs:639
Task< int > ReadAsync(byte[] buffer, int offset, int count)
Definition Stream.cs:762
static byte Min(byte val1, byte val2)
Definition Math.cs:912
static readonly Version Version20
static Exception CreateOperationCanceledException(Exception innerException, CancellationToken cancellationToken)
static void ThrowIfCancellationRequested(CancellationToken cancellationToken)
static void ProcessReceivedCookies(HttpResponseMessage response, CookieContainer cookieContainer)
ValueTask< int > RequestCreditAsync(int amount, CancellationToken cancellationToken)
void ResetForAwait(CancellationToken cancellationToken)
ValueTask< int > AsValueTask()
bool TrySetResult(int result)
static EmptyReadStream Instance
void Decode(ReadOnlySpan< byte > data, bool endHeaders, IHttpHeadersHandler handler)
static bool EncodeIndexedHeaderField(int index, Span< byte > destination, out int bytesWritten)
static bool EncodeStringLiterals(ReadOnlySpan< string > values, string separator, Encoding valueEncoding, Span< byte > destination, out int bytesWritten)
static bool EncodeLiteralHeaderFieldWithoutIndexing(int index, string value, Encoding valueEncoding, Span< byte > destination, out int bytesWritten)
static bool EncodeStringLiteral(string value, Encoding valueEncoding, Span< byte > destination, out int bytesWritten)
static bool EncodeLiteralHeaderFieldWithoutIndexingNewName(string name, ReadOnlySpan< string > values, string separator, Encoding valueEncoding, Span< byte > destination, out int bytesWritten)
bool TryAddWithoutValidation(string name, string? value)
static int GetStoreValuesIntoStringArray(HeaderDescriptor descriptor, object sourceValues, [NotNull] ref string[] values)
static readonly KnownHeader StrictTransportSecurity
static readonly KnownHeader ProxyAuthorization
static readonly KnownHeader ContentLanguage
static readonly KnownHeader RetryAfter
static readonly KnownHeader IfModifiedSince
static readonly KnownHeader Referer
static readonly KnownHeader Host
static readonly KnownHeader IfUnmodifiedSince
static readonly KnownHeader Date
static readonly KnownHeader LastModified
static readonly KnownHeader ContentRange
static readonly KnownHeader IfRange
static readonly KnownHeader Expect
static readonly KnownHeader SetCookie
static readonly KnownHeader AcceptLanguage
static readonly KnownHeader ProxyAuthenticate
static readonly KnownHeader Age
static readonly KnownHeader ContentDisposition
static readonly KnownHeader TransferEncoding
static readonly KnownHeader Refresh
static readonly KnownHeader IfNoneMatch
static readonly KnownHeader Server
static readonly KnownHeader ETag
static readonly KnownHeader Accept
static readonly KnownHeader AccessControlAllowOrigin
static readonly KnownHeader ContentType
static readonly KnownHeader IfMatch
static readonly KnownHeader ContentLength
static readonly KnownHeader UserAgent
static readonly KnownHeader AcceptCharset
static readonly KnownHeader AcceptEncoding
static readonly KnownHeader Connection
static readonly KnownHeader ContentLocation
static readonly KnownHeader TE
static readonly KnownHeader ProxyConnection
static readonly KnownHeader WWWAuthenticate
static readonly KnownHeader MaxForwards
static readonly KnownHeader CacheControl
static readonly KnownHeader ContentEncoding
static readonly KnownHeader AcceptRanges
static readonly KnownHeader Upgrade
static readonly KnownHeader Link
static readonly KnownHeader Authorization
static readonly KnownHeader Allow
static readonly KnownHeader Vary
static readonly KnownHeader Range
static readonly KnownHeader Via
static readonly KnownHeader Location
static readonly KnownHeader Cookie
static readonly KnownHeader Expires
static readonly KnownHeader From
override void Write(ReadOnlySpan< byte > buffer)
override void CopyTo(Stream destination, int bufferSize)
override ValueTask WriteAsync(ReadOnlyMemory< byte > destination, CancellationToken cancellationToken)
override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
override ValueTask< int > ReadAsync(Memory< byte > destination, CancellationToken cancellationToken)
override ValueTask WriteAsync(ReadOnlyMemory< byte > buffer, CancellationToken cancellationToken)
override Task FlushAsync(CancellationToken cancellationToken)
override ValueTask< int > ReadAsync(Memory< byte > buffer, CancellationToken cancellationToken)
CancellationTokenRegistration RegisterRequestBodyCancellation(CancellationToken cancellationToken)
static readonly(HeaderDescriptor descriptor, byte[] value)[] s_hpackStaticHeaderTable
CancellationTokenRegistration _waitSourceCancellation
void MoveTrailersToResponseMessage(HttpResponseMessage responseMessage)
void OnReset(Exception resetException, Http2ProtocolErrorCode? resetStreamErrorCode=null, bool canRetry=false)
System.Net.MultiArrayBuffer _responseBuffer
void CopyTo(HttpResponseMessage responseMessage, Stream destination, int bufferSize)
async Task ReadResponseHeadersAsync(CancellationToken cancellationToken)
bool int bytesRead TryReadFromBuffer(Span< byte > buffer, bool partOfSyncRead=false)
static ReadOnlySpan< byte > StatusHeaderName
ManualResetValueTaskSourceCore< bool > _waitSource
async ValueTask< bool > WaitFor100ContinueAsync(CancellationToken cancellationToken)
async ValueTask SendDataAsync(ReadOnlyMemory< byte > buffer, CancellationToken cancellationToken)
void Initialize(int streamId, int initialWindowSize)
void OnResponseData(ReadOnlySpan< byte > buffer, bool endStream)
async ValueTask< int > ReadDataAsync(Memory< byte > buffer, HttpResponseMessage responseMessage, CancellationToken cancellationToken)
async Task CopyToAsync(HttpResponseMessage responseMessage, Stream destination, int bufferSize, CancellationToken cancellationToken)
readonly CancellationTokenSource _requestBodyCancellationSource
Http2Stream(HttpRequestMessage request, Http2Connection connection)
void Trace(string message, [CallerMemberName] string memberName=null)
int ReadData(Span< byte > buffer, HttpResponseMessage responseMessage)
async Task SendRequestBodyAsync(CancellationToken cancellationToken)
readonly TaskCompletionSource< bool > _expect100ContinueWaiter
ValueTask WaitForDataAsync(CancellationToken cancellationToken)
void OnHeader(ReadOnlySpan< byte > name, ReadOnlySpan< byte > value)
void OnHeader(HeaderDescriptor descriptor, ReadOnlySpan< byte > value)
static readonly NopHeadersHandler Instance
WriteQueueEntry(int writeBytes, T state, Func< T, Memory< byte >, bool > writeAction, CancellationToken cancellationToken)
WriteQueueEntry(int writeBytes, CancellationToken cancellationToken)
bool InvokeWriteAction(Memory< byte > writeBuffer)
readonly Func< T, Memory< byte >, bool > _writeAction
override bool InvokeWriteAction(Memory< byte > writeBuffer)
readonly CancellationTokenRegistration _cancellationRegistration
TaskCompletionSource _shutdownWaiter
void WriteLiteralHeaderValues(ReadOnlySpan< string > values, string separator, Encoding valueEncoding, ref System.Net.ArrayBuffer headerBuffer)
void Trace(int streamId, string message, [CallerMemberName] string memberName=null)
static ReadOnlyMemory< byte > ReadOnlyMemory< byte > rest SplitBuffer(ReadOnlyMemory< byte > buffer, int maxSize)
Task FlushAsync(CancellationToken cancellationToken)
static void ThrowProtocolError(Http2ProtocolErrorCode errorCode)
Task SendWindowUpdateAsync(int streamId, int amount)
void WriteIndexedHeader(int index, ref System.Net.ArrayBuffer headerBuffer)
override long GetIdleTicks(long nowTicks)
void WriteHeaders(HttpRequestMessage request, ref System.Net.ArrayBuffer headerBuffer)
static ReadOnlyMemory< byte > first
async ValueTask< Http2Stream > SendHeadersAsync(HttpRequestMessage request, CancellationToken cancellationToken, bool mustFlush)
void ProcessPingFrame(FrameHeader frameHeader)
void ProcessRstStreamFrame(FrameHeader frameHeader)
void WriteHeaderCollection(HttpRequestMessage request, HttpHeaders headers, ref System.Net.ArrayBuffer headerBuffer)
TaskCompletionSource< bool > _availableStreamsWaiter
void ProcessSettingsFrame(FrameHeader frameHeader, bool initialFrame=false)
System.Net.ArrayBuffer _incomingBuffer
void WriteLiteralHeader(string name, ReadOnlySpan< string > values, Encoding valueEncoding, ref System.Net.ArrayBuffer headerBuffer)
void WriteLiteralHeaderValue(string value, Encoding valueEncoding, ref System.Net.ArrayBuffer headerBuffer)
readonly Channel< WriteQueueEntry > _writeChannel
ReadOnlySpan< byte > GetFrameData(ReadOnlySpan< byte > frameData, bool hasPad, bool hasPriority)
System.Net.ArrayBuffer _outgoingBuffer
volatile KeepAliveState _keepAliveState
void ProcessPriorityFrame(FrameHeader frameHeader)
static readonly byte[] s_http2ConnectionPreface
Task PerformWriteAsync< T >(int writeBytes, T state, Func< T, Memory< byte >, bool > writeAction, CancellationToken cancellationToken=default(CancellationToken))
async Task SendStreamDataAsync(int streamId, ReadOnlyMemory< byte > buffer, bool finalFlush, CancellationToken cancellationToken)
readonly HttpConnectionPool _pool
Task SendRstStreamAsync(int streamId, Http2ProtocolErrorCode errorCode)
void SignalAvailableStreamsWaiter(bool result)
ValueTask< bool > WaitForAvailableStreamsAsync()
override void Trace(string message, [CallerMemberName] string memberName=null)
static readonly UnboundedChannelOptions s_channelOptions
void Abort(Exception abortException)
void ProcessAltSvcFrame(FrameHeader frameHeader)
readonly CreditManager _connectionWindow
readonly HPackDecoder _hpackDecoder
void ProcessGoAwayFrame(FrameHeader frameHeader)
static void ThrowRetry(string message, Exception innerException=null)
void RemoveStream(Http2Stream http2Stream)
async ValueTask ProcessHeadersFrame(FrameHeader frameHeader)
void ChangeMaxConcurrentStreams(uint newValue)
static void ThrowRequestAborted(Exception innerException=null)
readonly Dictionary< int, Http2Stream > _httpStreams
void WriteBytes(ReadOnlySpan< byte > bytes, ref System.Net.ArrayBuffer headerBuffer)
async Task< HttpResponseMessage > SendAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken)
void ProcessDataFrame(FrameHeader frameHeader)
static Exception GetRequestAbortedException(Exception innerException=null)
Http2Connection(HttpConnectionPool pool, Stream stream)
async ValueTask< FrameHeader > ReadFrameAsync(bool initialFrame=false)
Http2Stream GetStream(int streamId)
void WriteIndexedHeader(int index, string value, ref System.Net.ArrayBuffer headerBuffer)
void ProcessWindowUpdateFrame(FrameHeader frameHeader)
void AddStream(Http2Stream http2Stream)
readonly HttpKeepAlivePingPolicy _keepAlivePingPolicy
Task SendPingAsync(long pingContent, bool isAck=false)
void ChangeInitialWindowSize(int newSize)
string GetResponseHeaderValueWithCaching(HeaderDescriptor descriptor, ReadOnlySpan< byte > value, Encoding valueEncoding)
static int ParseStatusCode(ReadOnlySpan< byte > value)
void HandleAltSvc(IEnumerable< string > altSvcHeaderValues, TimeSpan? responseAge)
HeaderEncodingSelector< HttpRequestMessage > _responseHeaderEncodingSelector
HeaderEncodingSelector< HttpRequestMessage > _requestHeaderEncodingSelector
ValueTask InternalCopyToAsync(Stream stream, TransportContext context, CancellationToken cancellationToken)
HttpContentHeaders Headers
static HttpMethod Normalize(HttpMethod method)
static HttpMethod Get
Definition HttpMethod.cs:35
static HttpMethod Post
Definition HttpMethod.cs:39
static readonly HttpTelemetry Log
static readonly System.Net.NetEventSource Log
static string net_http_invalid_response
Definition SR.cs:92
static string net_http_invalid_response_missing_frame
Definition SR.cs:96
static string net_http_response_headers_exceeded_length
Definition SR.cs:124
static string net_http_content_readonly_stream
Definition SR.cs:44
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string net_http_client_execution_error
Definition SR.cs:58
static string net_http_http2_connection_not_established
Definition SR.cs:150
static string net_http_server_shutdown
Definition SR.cs:172
static string net_http_invalid_response_premature_eof_bytecount
Definition SR.cs:98
static string net_http_request_aborted
Definition SR.cs:120
static string net_http_invalid_response_multiple_status_codes
Definition SR.cs:112
static string net_http_invalid_response_header_name
Definition SR.cs:118
static string net_http_invalid_response_pseudo_header_in_trailer
Definition SR.cs:122
Definition SR.cs:7
static Encoding ASCII
Definition Encoding.cs:511
static int Exchange(ref int location1, int value)
static long Read(ref long location)
static int Increment(ref int location)
new ConfiguredTaskAwaitable< TResult > ConfigureAwait(bool continueOnCapturedContext)
Definition Task.cs:226
static Task FromException(Exception exception)
Definition Task.cs:3341
static Task FromCanceled(CancellationToken cancellationToken)
Definition Task.cs:3363
static Task CompletedTask
Definition Task.cs:1120
new TaskAwaiter< TResult > GetAwaiter()
Definition Task.cs:221
static Task< Task > WhenAny(params Task[] tasks)
Definition Task.cs:3642
static readonly TimeSpan InfiniteTimeSpan
Definition Timeout.cs:5
void OnHeader(ReadOnlySpan< byte > name, ReadOnlySpan< byte > value)
void OnCompleted(Action< object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
ValueTaskSourceStatus GetStatus(short token)
static bool TryGet(string headerName, out HeaderDescriptor descriptor)
string GetHeaderValue(ReadOnlySpan< byte > headerValue, Encoding valueEncoding)
static FrameHeader ReadFrom(ReadOnlySpan< byte > buffer)
static void WriteTo(Span< byte > destination, int payloadLength, FrameType type, FrameFlags flags, int streamId)
FrameHeader(int payloadLength, FrameType type, FrameFlags flags, int streamId)
void AjdustWindowStatic(int bytesConsumed, Http2Stream stream)
Http2StreamWindowManager(Http2Connection connection, Http2Stream stream)
static TimeSpan StopwatchTicksToTimeSpan(long stopwatchTicks)
void AdjustWindow(int bytesConsumed, Http2Stream stream)
void AdjustWindowDynamic(int bytesConsumed, Http2Stream stream)
void OnInitialSettingsAckReceived(Http2Connection connection)
void RefreshRtt(Http2Connection connection)
void OnPingAckReceived(long payload, Http2Connection connection)
void OnDataOrHeadersReceived(Http2Connection connection)
void OnCompleted(Action< object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
static ValueTask FromCanceled(CancellationToken cancellationToken)
Definition ValueTask.cs:180
ConfiguredValueTaskAwaitable ConfigureAwait(bool continueOnCapturedContext)
Definition ValueTask.cs:312
static ValueTask FromException(Exception exception)
Definition ValueTask.cs:190
static TimeSpan FromSeconds(double value)
Definition TimeSpan.cs:247
static readonly TimeSpan Zero
Definition TimeSpan.cs:21