From 61c51f74292c7837547e901d50e2d05294b58f60 Mon Sep 17 00:00:00 2001 From: Geoff Kizer Date: Tue, 2 Jul 2019 03:22:04 -0700 Subject: [PATCH] clean up HTTP2 protocol exception handling Commit migrated from https://github.com/dotnet/corefx/commit/63e8aa4481928d4dc58c4cb563bfab7fdde322d0 --- .../System/Net/Http/Http2LoopbackConnection.cs | 2 +- .../System.Net.Http/src/Resources/Strings.resx | 11 ++--- .../System.Net.Http/src/System.Net.Http.csproj | 2 + .../Net/Http/SocketsHttpHandler/Http2Connection.cs | 52 +++++++++++----------- .../SocketsHttpHandler/Http2ConnectionException.cs | 17 +++++++ .../SocketsHttpHandler/Http2ProtocolException.cs | 18 +++----- .../Net/Http/SocketsHttpHandler/Http2Stream.cs | 27 +++++------ .../SocketsHttpHandler/Http2StreamException.cs | 17 +++++++ .../FunctionalTests/HttpClientHandlerTest.Http2.cs | 15 ++++--- 9 files changed, 97 insertions(+), 64 deletions(-) create mode 100644 src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2ConnectionException.cs create mode 100644 src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2StreamException.cs diff --git a/src/libraries/Common/tests/System/Net/Http/Http2LoopbackConnection.cs b/src/libraries/Common/tests/System/Net/Http/Http2LoopbackConnection.cs index 9f95c8b..f9e2939 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http2LoopbackConnection.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http2LoopbackConnection.cs @@ -484,7 +484,7 @@ namespace System.Net.Test.Common } } - private static int EncodeHeader(HttpHeaderData headerData, Span headerBlock) + public static int EncodeHeader(HttpHeaderData headerData, Span headerBlock) { // Always encode as literal, no indexing. int bytesGenerated = EncodeInteger(0, 0, 0b11110000, headerBlock); diff --git a/src/libraries/System.Net.Http/src/Resources/Strings.resx b/src/libraries/System.Net.Http/src/Resources/Strings.resx index 07aa988..ada59bf 100644 --- a/src/libraries/System.Net.Http/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Http/src/Resources/Strings.resx @@ -444,14 +444,11 @@ Error {0} calling {1}, '{2}'. - - The HTTP/2 request failed with protocol error '{0}' (0x{1}). + + The HTTP/2 server sent invalid data on the connection. HTTP/2 error code '{0}' (0x{1}). - - The HTTP/2 request failed with protocol error '{0}' ({1}). - - - The HTTP/2 request encountered a protocol error, receiving '{0}' while in the state '{1}'. + + The HTTP/2 server reset the stream. HTTP/2 error code '{0}' (0x{1}). This method is not implemented by this class. diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj index b327ba2..c7fd00d 100644 --- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj @@ -141,9 +141,11 @@ + + diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs index 2ef5934..dbac09e 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs @@ -199,7 +199,7 @@ namespace System.Net.Http } _incomingBuffer.Discard(FrameHeader.Size); - throw new Http2ProtocolException(initialFrame ? Http2ProtocolErrorCode.ProtocolError : Http2ProtocolErrorCode.FrameSizeError); + throw new Http2ConnectionException(initialFrame ? Http2ProtocolErrorCode.ProtocolError : Http2ProtocolErrorCode.FrameSizeError); } _incomingBuffer.Discard(FrameHeader.Size); @@ -216,7 +216,7 @@ namespace System.Net.Http FrameHeader frameHeader = await ReadFrameAsync(initialFrame: true).ConfigureAwait(false); if (frameHeader.Type != FrameType.Settings || frameHeader.AckFlag) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } if (NetEventSource.IsEnabled) Trace($"Frame 0: {frameHeader}."); @@ -266,7 +266,7 @@ namespace System.Net.Http case FrameType.PushPromise: // Should not happen, since we disable this in our initial SETTINGS (TODO: ISSUE 31295: We aren't currently, but we should) case FrameType.Continuation: // Should only be received while processing headers in ProcessHeadersFrame default: - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } } } @@ -292,7 +292,7 @@ namespace System.Net.Http // addition to the highest ID used by the client. if (streamId <= 0 || streamId >= _nextStream) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } lock (SyncObject) @@ -338,7 +338,7 @@ namespace System.Net.Http if (frameHeader.Type != FrameType.Continuation || frameHeader.StreamId != streamId) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } _hpackDecoder.Decode( @@ -368,7 +368,7 @@ namespace System.Net.Http { if (frameData.Length == 0) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } int padLength = frameData[0]; @@ -376,7 +376,7 @@ namespace System.Net.Http if (frameData.Length < padLength) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } frameData = frameData.Slice(0, frameData.Length - padLength); @@ -386,7 +386,7 @@ namespace System.Net.Http { if (frameData.Length < FrameHeader.PriorityInfoLength) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } // We ignore priority info. @@ -433,19 +433,19 @@ namespace System.Net.Http if (frameHeader.StreamId != 0) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } if (frameHeader.AckFlag) { if (frameHeader.Length != 0) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.FrameSizeError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.FrameSizeError); } if (!_expectingSettingsAck) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } // We only send SETTINGS once initially, so we don't need to do anything in response to the ACK. @@ -456,7 +456,7 @@ namespace System.Net.Http { if ((frameHeader.Length % 6) != 0) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.FrameSizeError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.FrameSizeError); } // Parse settings and process the ones we care about. @@ -479,7 +479,7 @@ namespace System.Net.Http case SettingId.InitialWindowSize: if (settingValue > 0x7FFFFFFF) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.FlowControlError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.FlowControlError); } ChangeInitialWindowSize((int)settingValue); @@ -488,7 +488,7 @@ namespace System.Net.Http case SettingId.MaxFrameSize: if (settingValue < 16384 || settingValue > 16777215) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } // We don't actually store this value; we always send frames of the minimum size (16K). @@ -547,7 +547,7 @@ namespace System.Net.Http if (frameHeader.StreamId == 0 || frameHeader.Length != FrameHeader.PriorityInfoLength) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } // Ignore priority info. @@ -561,18 +561,18 @@ namespace System.Net.Http if (frameHeader.StreamId != 0) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } if (frameHeader.AckFlag) { // We never send PING, so an ACK indicates a protocol error - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } if (frameHeader.Length != FrameHeader.PingLength) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.FrameSizeError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.FrameSizeError); } // Send PING ACK @@ -588,7 +588,7 @@ namespace System.Net.Http if (frameHeader.Length != FrameHeader.WindowUpdateLength) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.FrameSizeError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.FrameSizeError); } int amount = BinaryPrimitives.ReadInt32BigEndian(_incomingBuffer.ActiveSpan) & 0x7FFFFFFF; @@ -597,7 +597,7 @@ namespace System.Net.Http Debug.Assert(amount >= 0); if (amount == 0) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } _incomingBuffer.Discard(frameHeader.Length); @@ -625,12 +625,12 @@ namespace System.Net.Http if (frameHeader.Length != FrameHeader.RstStreamLength) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.FrameSizeError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.FrameSizeError); } if (frameHeader.StreamId == 0) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } Http2Stream http2Stream = GetStream(frameHeader.StreamId); @@ -652,7 +652,7 @@ namespace System.Net.Http } else { - http2Stream.OnAbort(new Http2ProtocolException(protocolError)); + http2Stream.OnAbort(new Http2StreamException(protocolError)); } RemoveStream(http2Stream); @@ -664,21 +664,21 @@ namespace System.Net.Http if (frameHeader.Length < FrameHeader.GoAwayMinLength) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.FrameSizeError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.FrameSizeError); } // GoAway frames always apply to the whole connection, never to a single stream. // According to RFC 7540 section 6.8, this should be a connection error. if (frameHeader.StreamId != 0) { - throw new Http2ProtocolException(Http2ProtocolErrorCode.ProtocolError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } int lastValidStream = (int)(BinaryPrimitives.ReadUInt32BigEndian(_incomingBuffer.ActiveSpan) & 0x7FFFFFFF); var errorCode = (Http2ProtocolErrorCode)BinaryPrimitives.ReadInt32BigEndian(_incomingBuffer.ActiveSpan.Slice(sizeof(int))); if (NetEventSource.IsEnabled) Trace(frameHeader.StreamId, $"{nameof(lastValidStream)}={lastValidStream}, {nameof(errorCode)}={errorCode}"); - AbortStreams(lastValidStream, new Http2ProtocolException(errorCode)); + AbortStreams(lastValidStream, new Http2ConnectionException(errorCode)); _incomingBuffer.Discard(frameHeader.Length); } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2ConnectionException.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2ConnectionException.cs new file mode 100644 index 0000000..1769d32 --- /dev/null +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2ConnectionException.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.Serialization; + +namespace System.Net.Http +{ + [Serializable] + internal sealed class Http2ConnectionException : Http2ProtocolException + { + public Http2ConnectionException(Http2ProtocolErrorCode protocolError) + : base(SR.Format(SR.net_http_http2_connection_error, GetName(protocolError), ((int)protocolError).ToString("x")), protocolError) + { + } + } +} diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2ProtocolException.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2ProtocolException.cs index 7e51f69..2451b51 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2ProtocolException.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2ProtocolException.cs @@ -2,26 +2,19 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Diagnostics; using System.Runtime.Serialization; namespace System.Net.Http { [Serializable] - internal sealed class Http2ProtocolException : Exception + internal abstract class Http2ProtocolException : Exception { - public Http2ProtocolException(Http2ProtocolErrorCode protocolError) - : base(SR.Format(SR.net_http_http2_protocol_error, GetName(protocolError), ((int)protocolError).ToString("x"))) + public Http2ProtocolException(string message, Http2ProtocolErrorCode protocolError) + : base(message) { ProtocolError = protocolError; } - public Http2ProtocolException(string message) - : base(SR.Format(SR.net_http_http2_protocol_error_text, GetName(Http2ProtocolErrorCode.ProtocolError), message)) - { - ProtocolError = Http2ProtocolErrorCode.ProtocolError; - } - private Http2ProtocolException(SerializationInfo info, StreamingContext context) : base(info, context) { ProtocolError = (Http2ProtocolErrorCode)info.GetInt32(nameof(ProtocolError)); @@ -35,14 +28,13 @@ namespace System.Net.Http internal Http2ProtocolErrorCode ProtocolError { get; } - private static string GetName(Http2ProtocolErrorCode code) + protected static string GetName(Http2ProtocolErrorCode code) { // These strings are the names used in the HTTP2 spec and should not be localized. switch (code) { case Http2ProtocolErrorCode.NoError: return "NO_ERROR"; - default: // any unrecognized error code is treated as a protocol error case Http2ProtocolErrorCode.ProtocolError: return "PROTOCOL_ERROR"; case Http2ProtocolErrorCode.InternalError: @@ -69,6 +61,8 @@ namespace System.Net.Http return "INADEQUATE_SECURITY"; case Http2ProtocolErrorCode.Http11Required: return "HTTP_1_1_REQUIRED"; + default: + return "(unknown error)"; } } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs index 0297903..4af1519 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs @@ -231,7 +231,7 @@ namespace System.Net.Http { // Pseudo-headers are allowed only in header block if (NetEventSource.IsEnabled) Trace($"Pseudo-header received in {_state} state."); - throw new Http2ProtocolException(SR.net_http_invalid_response_pseudo_header_in_trailer); + throw new HttpRequestException(SR.net_http_invalid_response_pseudo_header_in_trailer); } if (name.SequenceEqual(s_statusHeaderName)) @@ -239,7 +239,7 @@ namespace System.Net.Http if (_state != StreamState.ExpectingStatus) { if (NetEventSource.IsEnabled) Trace("Received extra status header."); - throw new Http2ProtocolException(SR.Format(SR.net_http_invalid_response_status_code, "duplicate status")); + throw new HttpRequestException(SR.Format(SR.net_http_invalid_response_status_code, "duplicate status")); } byte status1, status2, status3; @@ -248,7 +248,7 @@ namespace System.Net.Http !IsDigit(status2 = value[1]) || !IsDigit(status3 = value[2])) { - throw new Http2ProtocolException(SR.Format(SR.net_http_invalid_response_status_code, Encoding.ASCII.GetString(value))); + throw new HttpRequestException(SR.Format(SR.net_http_invalid_response_status_code, Encoding.ASCII.GetString(value))); } int statusValue = (100 * (status1 - '0') + 10 * (status2 - '0') + (status3 - '0')); @@ -283,7 +283,7 @@ namespace System.Net.Http else { if (NetEventSource.IsEnabled) Trace($"Invalid response pseudo-header '{Encoding.ASCII.GetString(name)}'."); - throw new Http2ProtocolException(SR.net_http_invalid_response); + throw new HttpRequestException(SR.net_http_invalid_response); } } else @@ -297,13 +297,13 @@ namespace System.Net.Http if (_state != StreamState.ExpectingHeaders && _state != StreamState.ExpectingTrailingHeaders) { if (NetEventSource.IsEnabled) Trace("Received header before status."); - throw new Http2ProtocolException(SR.net_http_invalid_response); + throw new HttpRequestException(SR.net_http_invalid_response); } if (!HeaderDescriptor.TryGet(name, out HeaderDescriptor descriptor)) { // Invalid header name - throw new Http2ProtocolException(SR.Format(SR.net_http_invalid_response_header_name, Encoding.ASCII.GetString(name))); + throw new HttpRequestException(SR.Format(SR.net_http_invalid_response_header_name, Encoding.ASCII.GetString(name))); } string headerValue = descriptor.GetHeaderValue(value); @@ -337,7 +337,7 @@ namespace System.Net.Http if (_state != StreamState.ExpectingStatus && _state != StreamState.ExpectingData) { - throw new Http2ProtocolException(SR.Format(SR.net_http_http2_protocol_state, "headers", _state)); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } if (_state == StreamState.ExpectingData) @@ -359,7 +359,7 @@ namespace System.Net.Http if (_state != StreamState.ExpectingHeaders && _state != StreamState.ExpectingTrailingHeaders && _state != StreamState.ExpectingIgnoredHeaders) { - throw new Http2ProtocolException(SR.Format(SR.net_http_http2_protocol_state, "headers", _state)); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } if (_state == StreamState.ExpectingHeaders) @@ -370,8 +370,8 @@ namespace System.Net.Http { if (!endStream) { - if (NetEventSource.IsEnabled) Trace("Trailing headers received without endStream"); - throw new Http2ProtocolException(SR.net_http_invalid_response); + if (NetEventSource.IsEnabled) Trace("Trailing headers received without endStream"); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } _state = StreamState.Complete; @@ -381,7 +381,7 @@ namespace System.Net.Http if (endStream) { // we should not get endStream while processing 1xx response. - throw new Http2ProtocolException(SR.net_http_invalid_response); + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } _state = StreamState.ExpectingStatus; @@ -420,13 +420,14 @@ namespace System.Net.Http if (_state != StreamState.ExpectingData) { - throw new Http2ProtocolException(SR.Format(SR.net_http_http2_protocol_state, "data", _state)); + // Flow control messages are not valid in this state. + throw new Http2ConnectionException(Http2ProtocolErrorCode.ProtocolError); } if (_responseBuffer.ActiveSpan.Length + buffer.Length > StreamWindowSize) { // Window size exceeded. - throw new Http2ProtocolException(Http2ProtocolErrorCode.FlowControlError); + throw new Http2ConnectionException(Http2ProtocolErrorCode.FlowControlError); } _responseBuffer.EnsureAvailableSpace(buffer.Length); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2StreamException.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2StreamException.cs new file mode 100644 index 0000000..f0c2602 --- /dev/null +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2StreamException.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Runtime.Serialization; + +namespace System.Net.Http +{ + [Serializable] + internal sealed class Http2StreamException : Http2ProtocolException + { + public Http2StreamException(Http2ProtocolErrorCode protocolError) + : base(SR.Format(SR.net_http_http2_stream_error, GetName(protocolError), ((int)protocolError).ToString("x")), protocolError) + { + } + } +} diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs index 18d6a67..794f8d2 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http2.cs @@ -34,7 +34,7 @@ namespace System.Net.Http.Functional.Tests string text = e.ToString(); Assert.Contains(((int)errorCode).ToString("x"), text); Assert.Contains( - Enum.IsDefined(typeof(ProtocolErrors), errorCode) ? errorCode.ToString() : ProtocolErrors.PROTOCOL_ERROR.ToString(), + Enum.IsDefined(typeof(ProtocolErrors), errorCode) ? errorCode.ToString() : "(unknown error)", text); } } @@ -462,10 +462,15 @@ namespace System.Net.Http.Functional.Tests (endHeaders ? FrameFlags.EndHeaders : FrameFlags.None) | (endStream ? FrameFlags.EndStream : FrameFlags.None), 0, 0, 0, streamId); - private static Frame MakeSimpleContinuationFrame(int streamId, bool endHeaders = false) => - new ContinuationFrame(new byte[] { 0x88 }, // :status: 200 + private static Frame MakeSimpleContinuationFrame(int streamId, bool endHeaders = false) + { + Memory headerBlock = new byte[Frame.MaxFrameLength]; + int bytesGenerated = Http2LoopbackConnection.EncodeHeader(new HttpHeaderData("foo", "bar"), headerBlock.Span); + + return new ContinuationFrame(headerBlock.Slice(0, bytesGenerated), (endHeaders ? FrameFlags.EndHeaders : FrameFlags.None), 0, 0, 0, streamId); + } private static Frame MakeSimpleDataFrame(int streamId, bool endStream = false) => new DataFrame(new byte[] { 0x00 }, @@ -2071,9 +2076,9 @@ namespace System.Net.Http.Functional.Tests await response.Content.ReadAsStringAsync(); }); - // A Http2ProtocolException will be present somewhere in the inner exceptions. + // A Http2ConnectionException will be present somewhere in the inner exceptions. // Its location depends on which method threw the exception. - while (requestException?.GetType().FullName.Equals("System.Net.Http.Http2ProtocolException") == false) + while (requestException?.GetType().FullName.Equals("System.Net.Http.Http2ConnectionException") == false) { requestException = requestException.InnerException; } -- 2.7.4