Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,20 @@ internal enum Http3ErrorCode : long
/// The requested operation cannot be served over HTTP/3. The peer should retry over HTTP/1.1.
/// </summary>
VersionFallback = 0x110,
/// <summary>
/// H3_QPACK_DECOMPRESSION_FAILED (0x200):
/// The decoder failed to interpret an encoded field section and is not able to continue decoding that field section.
/// </summary>
QPackDecompressionFailed = 0x200,
/// <summary>
/// H3_QPACK_ENCODER_STREAM_ERROR (0x201):
/// The decoder failed to interpret an encoder instruction received on the encoder stream.
/// </summary>
QPackEncoderStreamError = 0x201,
/// <summary>
/// H3_QPACK_DECODER_STREAM_ERROR (0x202):
/// The encoder failed to interpret an decoder instruction received on the decoder stream.
/// </summary>
QPackDecoderStreamError = 0x202,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,12 @@ await Task.WhenAny(sendRequestTask, readResponseTask).ConfigureAwait(false) == s
}
catch (QuicException ex) when (ex.QuicError == QuicError.OperationAborted && _connection.AbortException != null)
{
// we close the connection, propagate the AbortException
throw new HttpRequestException(HttpRequestError.Unknown, SR.net_http_client_execution_error, _connection.AbortException);
// we closed the connection already, propagate the AbortException
HttpRequestError httpRequestError = _connection.AbortException is HttpProtocolException
? HttpRequestError.HttpProtocolError
: HttpRequestError.Unknown;

throw new HttpRequestException(httpRequestError, SR.net_http_client_execution_error, _connection.AbortException);
}
// It is possible for user's Content code to throw an unexpected OperationCanceledException.
catch (OperationCanceledException ex) when (ex.CancellationToken == _requestBodyCancellationSource.Token || ex.CancellationToken == cancellationToken)
Expand All @@ -300,13 +304,26 @@ await Task.WhenAny(sendRequestTask, readResponseTask).ConfigureAwait(false) == s
_connection.Abort(ex);
throw new HttpRequestException(ex.HttpRequestError, SR.net_http_client_execution_error, ex);
}
catch (QPackDecodingException ex)
{
Exception abortException = _connection.Abort(HttpProtocolException.CreateHttp3ConnectionException(Http3ErrorCode.QPackDecompressionFailed));
throw new HttpRequestException(HttpRequestError.InvalidResponse, SR.net_http_invalid_response, ex);
}
catch (QPackEncodingException ex)
{
_stream.Abort(QuicAbortDirection.Write, (long)Http3ErrorCode.InternalError);
throw new HttpRequestException(HttpRequestError.Unknown, SR.net_http_client_execution_error, ex);
}
Comment thread
MihaZupan marked this conversation as resolved.
catch (Exception ex)
{
_stream.Abort(QuicAbortDirection.Write, (long)Http3ErrorCode.InternalError);
if (ex is HttpRequestException)
{
throw;
}

// all exceptions should be already handled above
Debug.Fail($"Unexpected exception type in Http3RequestStream.SendAsync: {ex}");
throw new HttpRequestException(HttpRequestError.Unknown, SR.net_http_client_execution_error, ex);
}
finally
Expand Down Expand Up @@ -1253,6 +1270,13 @@ private void HandleReadResponseContentException(Exception ex, CancellationToken
_connection.Abort(exception);
throw exception;

case QuicException e when (e.QuicError == QuicError.OperationAborted && _connection.AbortException != null):
// we closed the connection already, propagate the AbortException
HttpRequestError httpRequestError = _connection.AbortException is HttpProtocolException
? HttpRequestError.HttpProtocolError
: HttpRequestError.Unknown;
throw new HttpRequestException(httpRequestError, SR.net_http_client_execution_error, _connection.AbortException);

case HttpIOException:
_connection.Abort(ex);
ExceptionDispatchInfo.Throw(ex); // Rethrow.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ private async Task AssertProtocolErrorAsync(long errorCode, Func<Task> task)
{
Exception outerEx = await Assert.ThrowsAnyAsync<Exception>(task);
_output.WriteLine(outerEx.ToString());
Assert.IsType<HttpRequestException>(outerEx);

HttpRequestException httpReqException = Assert.IsType<HttpRequestException>(outerEx);
Assert.Equal(HttpRequestError.HttpProtocolError, httpReqException.HttpRequestError);

HttpProtocolException protocolEx = Assert.IsType<HttpProtocolException>(outerEx.InnerException);
Assert.Equal(errorCode, protocolEx.ErrorCode);
}
Expand Down Expand Up @@ -1759,7 +1762,14 @@ public async Task ServerClosesOutboundControlStream_ClientClosesConnection(Close
return;
}
await connection.OutboundControlStream.DisposeAsync();
await connection.EstablishControlStreamAsync(Array.Empty<SettingsEntry>());
try
{
await connection.EstablishControlStreamAsync(Array.Empty<SettingsEntry>());
}
catch (QuicException ex) when (ex.QuicError == QuicError.ConnectionAborted && ex.ApplicationErrorCode == Http3LoopbackConnection.H3_CLOSED_CRITICAL_STREAM)
{
// Data race, connection closed between WaitAsync and EstablishControlStreamAsync. Ignore this.
}
await Task.Delay(100);
}
}
Expand Down