Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
Http3Connection.cs
Go to the documentation of this file.
3using System.IO;
11
12namespace System.Net.Http;
13
14[SupportedOSPlatform("windows")]
15[SupportedOSPlatform("linux")]
16[SupportedOSPlatform("macos")]
17internal sealed class Http3Connection : HttpConnectionBase
18{
19 private readonly HttpConnectionPool _pool;
20
21 private readonly HttpAuthority _origin;
22
23 private readonly HttpAuthority _authority;
24
25 private readonly byte[] _altUsedEncodedHeader;
26
28
30
32
33 private long _lastProcessedStreamId = -1L;
34
36
37 private int _maximumHeadersLength = int.MaxValue;
38
40
42
44
46
48
50
52
54
55 private object SyncObj => _activeRequests;
56
57 private bool ShuttingDown => _lastProcessedStreamId != -1;
58
60 {
61 _pool = pool;
62 _origin = origin;
64 _connection = connection;
65 string text;
66 if ((pool.Kind != 0 || authority.Port != 80) && (pool.Kind != HttpConnectionKind.Https || authority.Port != 443))
67 {
70 handler.AppendFormatted(authority.IdnHost);
71 handler.AppendLiteral(":");
72 handler.AppendFormatted(authority.Port);
73 text = string.Create(invariantCulture, ref handler);
74 }
75 else
76 {
77 text = authority.IdnHost;
78 }
79 string value = text;
83 }
84
85 public override void Dispose()
86 {
88 {
89 if (_lastProcessedStreamId == -1)
90 {
91 _lastProcessedStreamId = long.MaxValue;
93 }
94 }
95 }
96
97 private void CheckForShutdown()
98 {
99 if (_activeRequests.Count != 0 || _connection == null)
100 {
101 return;
102 }
103 if (_connectionClosedTask == null)
104 {
106 }
107 QuicConnection connection = _connection;
108 _connection = null;
110 {
111 if (closeTask.IsFaulted && System.Net.NetEventSource.Log.IsEnabled())
112 {
113 Trace($"{"QuicConnection"} failed to close: {closeTask.Exception.InnerException}", "CheckForShutdown");
114 }
115 try
116 {
117 connection.Dispose();
118 }
120 {
121 Trace($"{"QuicConnection"} failed to dispose: {value}", "CheckForShutdown");
122 }
123 if (_clientControl != null)
124 {
126 _clientControl = null;
127 }
129 }
130
132 {
133 QuicStream quicStream = null;
135 ValueTask valueTask = default(ValueTask);
136 try
137 {
138 while (true)
139 {
140 lock (SyncObj)
141 {
142 if (_connection != null)
143 {
145 {
147 goto IL_00ce;
148 }
152 }
153 }
154 break;
155 IL_00ce:
156 await valueTask.ConfigureAwait(continueOnCapturedContext: false);
157 }
158 if (quicStream == null)
159 {
160 throw new HttpRequestException(System.SR.net_http_request_aborted, null, RequestRetryType.RetryOnConnectionFailure);
161 }
162 requestStream.StreamId = quicStream.StreamId;
163 bool flag;
164 lock (SyncObj)
165 {
166 flag = _lastProcessedStreamId != -1 && requestStream.StreamId > _lastProcessedStreamId;
167 }
168 if (flag)
169 {
170 throw new HttpRequestException(System.SR.net_http_request_aborted, null, RequestRetryType.RetryOnConnectionFailure);
171 }
173 requestStream = null;
174 return await task.ConfigureAwait(continueOnCapturedContext: false);
175 }
177 {
178 Abort(ex);
179 throw new HttpRequestException(System.SR.Format(System.SR.net_http_http3_connection_error, ex.ErrorCode), ex, RequestRetryType.RetryOnConnectionFailure);
180 }
181 finally
182 {
183 requestStream?.Dispose();
184 }
185 }
186
188 {
190 if (ex != null)
191 {
192 if (System.Net.NetEventSource.Log.IsEnabled() && ex != abortException)
193 {
194 Trace($"{"abortException"}=={abortException}", "Abort");
195 }
196 return ex;
197 }
200 lock (SyncObj)
201 {
202 if (_lastProcessedStreamId == -1)
203 {
204 _lastProcessedStreamId = long.MaxValue;
205 }
206 if (_connection != null && _connectionClosedTask == null)
207 {
209 }
211 return abortException;
212 }
213 }
214
216 {
219 lock (SyncObj)
220 {
222 {
223 if (System.Net.NetEventSource.Log.IsEnabled())
224 {
225 Trace("HTTP/3 server sent GOAWAY with increasing stream ID. Retried requests may have been double-processed by server.", "OnServerGoAway");
226 }
227 return;
228 }
231 {
232 if (activeRequest.Value.StreamId > lastProcessedStreamId)
233 {
234 list.Add(activeRequest.Value);
235 }
236 }
238 }
239 foreach (Http3RequestStream item in list)
240 {
241 item.GoAway();
242 }
243 }
244
246 {
247 lock (SyncObj)
248 {
249 bool flag = _activeRequests.Remove(stream);
250 if (ShuttingDown)
251 {
253 }
254 }
255 }
256
257 public override long GetIdleTicks(long nowTicks)
258 {
259 throw new NotImplementedException("We aren't scavenging HTTP3 connections yet");
260 }
261
262 public override void Trace(string message, [CallerMemberName] string memberName = null)
263 {
264 Trace(0L, message, memberName);
265 }
266
267 internal void Trace(long streamId, string message, [CallerMemberName] string memberName = null)
268 {
269 System.Net.NetEventSource.Log.HandlerMessage(_pool?.GetHashCode() ?? 0, GetHashCode(), (int)streamId, memberName, message);
270 }
271
284
285 public static byte[] BuildSettingsFrame(HttpConnectionSettings settings)
286 {
287 Span<byte> span = stackalloc byte[12];
288 int num = VariableLengthIntegerHelper.WriteInteger(span.Slice(4), (long)settings._maxResponseHeadersLength * 1024L);
289 int num2 = 1 + num;
290 span[0] = 0;
291 span[1] = 4;
292 span[2] = (byte)num2;
293 span[3] = 6;
294 return span.Slice(0, 4 + num).ToArray();
295 }
296
298 {
299 try
300 {
301 while (true)
302 {
304 lock (SyncObj)
305 {
306 if (ShuttingDown)
307 {
308 break;
309 }
311 }
313 }
314 }
316 {
317 }
319 {
321 }
322 }
323
325 {
327 try
328 {
330 try
331 {
332 if (stream.CanWrite)
333 {
334 throw new Http3ConnectionException(Http3ErrorCode.StreamCreationError);
335 }
336 buffer = new System.Net.ArrayBuffer(32, usePool: true);
337 int num;
338 try
339 {
340 num = await stream.ReadAsync(buffer.AvailableMemory, CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false);
341 }
343 {
344 num = 0;
345 }
346 if (num == 0)
347 {
348 return;
349 }
350 buffer.Commit(num);
351 switch (buffer.ActiveSpan[0])
352 {
353 case 0:
354 {
356 {
357 throw new Http3ConnectionException(Http3ErrorCode.StreamCreationError);
358 }
359 buffer.Discard(1);
361 buffer = default(System.Net.ArrayBuffer);
363 return;
364 }
365 case 3:
367 {
368 throw new Http3ConnectionException(Http3ErrorCode.StreamCreationError);
369 }
370 buffer.Dispose();
371 await stream.CopyToAsync(Stream.Null).ConfigureAwait(continueOnCapturedContext: false);
372 return;
373 case 2:
375 {
376 throw new Http3ConnectionException(Http3ErrorCode.StreamCreationError);
377 }
378 buffer.Dispose();
379 await stream.CopyToAsync(Stream.Null).ConfigureAwait(continueOnCapturedContext: false);
380 return;
381 case 1:
382 throw new Http3ConnectionException(Http3ErrorCode.IdError);
383 }
384 if (System.Net.NetEventSource.Log.IsEnabled())
385 {
386 long value;
387 int bytesRead;
389 {
390 buffer.EnsureAvailableSpace(8);
391 num = await stream.ReadAsync(buffer.AvailableMemory, CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false);
392 if (num == 0)
393 {
394 value = -1L;
395 break;
396 }
397 buffer.Commit(num);
398 }
399 System.Net.NetEventSource.Info(this, $"Ignoring server-initiated stream of unknown type {value}.", "ProcessServerStreamAsync");
400 }
401 stream.AbortWrite(259L);
402 }
403 finally
404 {
406 if (asyncDisposable != null)
407 {
408 await asyncDisposable.DisposeAsync();
409 }
410 }
411 }
413 {
415 }
416 finally
417 {
418 buffer.Dispose();
419 }
420 }
421
423 {
424 using (buffer)
425 {
428 (http3FrameType, settingsPayloadLength2) = await ReadFrameEnvelopeAsync().ConfigureAwait(continueOnCapturedContext: false);
429 if (!http3FrameType.HasValue)
430 {
431 throw new Http3ConnectionException(Http3ErrorCode.ClosedCriticalStream);
432 }
433 if (http3FrameType != Http3FrameType.Settings)
434 {
435 throw new Http3ConnectionException(Http3ErrorCode.MissingSettings);
436 }
438 while (true)
439 {
440 (http3FrameType, settingsPayloadLength2) = await ReadFrameEnvelopeAsync().ConfigureAwait(continueOnCapturedContext: false);
441 if (!http3FrameType.HasValue)
442 {
443 break;
444 }
445 Http3FrameType valueOrDefault = http3FrameType.GetValueOrDefault();
446 if ((ulong)valueOrDefault <= 13uL)
447 {
448 switch (valueOrDefault)
449 {
450 case Http3FrameType.GoAway:
452 continue;
453 case Http3FrameType.Settings:
454 throw new Http3ConnectionException(Http3ErrorCode.UnexpectedFrame);
455 case Http3FrameType.Data:
456 case Http3FrameType.Headers:
457 case Http3FrameType.ReservedHttp2Priority:
458 case Http3FrameType.ReservedHttp2Ping:
459 case Http3FrameType.ReservedHttp2WindowUpdate:
460 case Http3FrameType.ReservedHttp2Continuation:
461 case Http3FrameType.MaxPushId:
462 throw new Http3ConnectionException(Http3ErrorCode.UnexpectedFrame);
463 case Http3FrameType.CancelPush:
464 case Http3FrameType.PushPromise:
465 throw new Http3ConnectionException(Http3ErrorCode.IdError);
466 }
467 }
468 await SkipUnknownPayloadAsync(http3FrameType.GetValueOrDefault(), settingsPayloadLength2).ConfigureAwait(continueOnCapturedContext: false);
469 }
470 bool shuttingDown;
471 lock (SyncObj)
472 {
474 }
475 if (!shuttingDown)
476 {
477 throw new Http3ConnectionException(Http3ErrorCode.ClosedCriticalStream);
478 }
479 }
481 {
482 long value;
483 int bytesRead;
485 {
486 buffer.EnsureAvailableSpace(8);
487 bytesRead = await stream.ReadAsync(buffer.AvailableMemory, CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false);
488 if (bytesRead == 0)
489 {
490 throw new Http3ConnectionException(Http3ErrorCode.FrameError);
491 }
492 buffer.Commit(bytesRead);
493 }
494 buffer.Discard(bytesRead);
496 {
497 throw new Http3ConnectionException(Http3ErrorCode.FrameError);
498 }
500 }
502 {
503 while (settingsPayloadLength != 0L)
504 {
505 long a;
506 long b;
507 int bytesRead2;
508 while (!Http3Frame.TryReadIntegerPair(buffer.ActiveSpan, out a, out b, out bytesRead2))
509 {
510 buffer.EnsureAvailableSpace(16);
511 bytesRead2 = await stream.ReadAsync(buffer.AvailableMemory, CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false);
512 if (bytesRead2 == 0)
513 {
514 throw new Http3ConnectionException(Http3ErrorCode.FrameError);
515 }
516 buffer.Commit(bytesRead2);
517 }
519 if (settingsPayloadLength < 0)
520 {
521 throw new Http3ConnectionException(Http3ErrorCode.FrameError);
522 }
523 buffer.Discard(bytesRead2);
524 switch ((Http3SettingType)a)
525 {
526 case Http3SettingType.MaxHeaderListSize:
527 _maximumHeadersLength = (int)Math.Min(b, 2147483647L);
528 break;
529 case Http3SettingType.ReservedHttp2EnablePush:
530 case Http3SettingType.ReservedHttp2MaxConcurrentStreams:
531 case Http3SettingType.ReservedHttp2InitialWindowSize:
532 case Http3SettingType.ReservedHttp2MaxFrameSize:
533 throw new Http3ConnectionException(Http3ErrorCode.SettingsError);
534 }
535 }
536 }
537 async ValueTask<(Http3FrameType? frameType, long payloadLength)> ReadFrameEnvelopeAsync()
538 {
539 long a2;
540 long b2;
541 int bytesRead3;
543 {
544 buffer.EnsureAvailableSpace(16);
545 bytesRead3 = await stream.ReadAsync(buffer.AvailableMemory, CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false);
546 if (bytesRead3 == 0)
547 {
548 if (buffer.ActiveLength == 0)
549 {
550 return (null, 0L);
551 }
552 throw new Http3ConnectionException(Http3ErrorCode.FrameError);
553 }
554 buffer.Commit(bytesRead3);
555 }
556 buffer.Discard(bytesRead3);
557 return ((Http3FrameType)a2, b2);
558 }
559 async ValueTask SkipUnknownPayloadAsync(Http3FrameType frameType, long payloadLength)
560 {
561 while (payloadLength != 0L)
562 {
563 if (buffer.ActiveLength == 0)
564 {
565 int num = await stream.ReadAsync(buffer.AvailableMemory, CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false);
566 if (num == 0)
567 {
568 throw new Http3ConnectionException(Http3ErrorCode.FrameError);
569 }
570 buffer.Commit(num);
571 }
572 long num2 = Math.Min(payloadLength, buffer.ActiveLength);
573 buffer.Discard((int)num2);
575 }
576 }
577 }
578}
bool ICollection< KeyValuePair< TKey, TValue > >. Remove(KeyValuePair< TKey, TValue > keyValuePair)
void Add(TKey key, TValue value)
static CultureInfo InvariantCulture
static readonly Stream Null
Definition Stream.cs:488
static byte Min(byte val1, byte val2)
Definition Math.cs:912
static readonly KnownHeader AltUsed
override void Trace(string message, [CallerMemberName] string memberName=null)
void RemoveStream(QuicStream stream)
async Task ProcessServerStreamAsync(QuicStream stream)
Exception Abort(Exception abortException)
async Task ProcessServerControlStreamAsync(QuicStream stream, System.Net.ArrayBuffer buffer)
void OnServerGoAway(long lastProcessedStreamId)
readonly HttpAuthority _origin
async Task< HttpResponseMessage > SendAsync(HttpRequestMessage request, bool async, CancellationToken cancellationToken)
readonly HttpAuthority _authority
void Trace(long streamId, string message, [CallerMemberName] string memberName=null)
readonly HttpConnectionPool _pool
Http3Connection(HttpConnectionPool pool, HttpAuthority origin, HttpAuthority authority, QuicConnection connection)
static byte[] BuildSettingsFrame(HttpConnectionSettings settings)
readonly Dictionary< QuicStream, Http3RequestStream > _activeRequests
override long GetIdleTicks(long nowTicks)
static bool TryReadIntegerPair(ReadOnlySpan< byte > buffer, out long a, out long b, out int bytesRead)
Definition Http3Frame.cs:5
void InvalidateHttp3Connection(Http3Connection connection)
static byte[] EncodeLiteralHeaderFieldWithoutNameReferenceToArray(string name)
static bool TryRead(ReadOnlySpan< byte > buffer, out long value, out int bytesRead)
static int WriteInteger(Span< byte > buffer, long longToEncode)
static readonly System.Net.NetEventSource Log
static void Info(object thisOrContextObject, FormattableString formattableString=null, [CallerMemberName] string memberName=null)
ValueTask CloseAsync(long errorCode, CancellationToken cancellationToken=default(CancellationToken))
ValueTask WaitForAvailableBidirectionalStreamsAsync(CancellationToken cancellationToken=default(CancellationToken))
async ValueTask< QuicStream > AcceptStreamAsync(CancellationToken cancellationToken=default(CancellationToken))
override void Dispose(bool disposing)
override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string net_http_http3_connection_error
Definition SR.cs:182
static string net_http_request_aborted
Definition SR.cs:120
Definition SR.cs:7
static int CompareExchange(ref int location1, int value, int comparand)
static int Exchange(ref int location1, int value)
Task ContinueWith(Action< Task< TResult > > continuationAction)
Definition Task.cs:263
static bool Read(ref bool location)
Definition Volatile.cs:67