public void Abort(ConnectionAbortedException ex, Http3ErrorCode errorCode) { _errorCodeFeature.Error = (long)errorCode; // TODO replace with IKestrelTrace log. Log.LogWarning(ex, ex.Message); _frameWriter.Abort(ex); }
public void Http3StreamAbort(string traceIdentifier, Http3ErrorCode error, ConnectionAbortedException abortReason) { if (_http3Logger.IsEnabled(LogLevel.Debug)) { Http3StreamAbort(_http3Logger, traceIdentifier, Http3Formatting.ToFormattedErrorCode(error), abortReason); } }
public void Abort(ConnectionAbortedException abortReason, Http3ErrorCode errorCode) { lock (_completionLock) { if (IsCompleted) { return; } var(oldState, newState) = ApplyCompletionFlag(StreamCompletionFlags.Aborted); if (oldState == newState) { return; } Log.Http3StreamAbort(TraceIdentifier, errorCode, abortReason); _errorCodeFeature.Error = (long)errorCode; _frameWriter.Abort(abortReason); // Call _http3Output.Stop() prior to poisoning the request body stream or pipe to // ensure that an app that completes early due to the abort doesn't result in header frames being sent. _http3Output.Stop(); CancelRequestAbortedToken(); // Unblock the request body. PoisonBody(abortReason); RequestBodyPipe.Writer.Complete(abortReason); } }
internal void AssertConnectionError <TException>(Http3ErrorCode expectedErrorCode, params string[] expectedErrorMessage) where TException : Exception { Assert.Equal((Http3ErrorCode)expectedErrorCode, (Http3ErrorCode)MultiplexedConnectionContext.Error); if (expectedErrorMessage?.Length > 0) { var message = Assert.Single(LogMessages, m => m.Exception is TException); Assert.Contains(expectedErrorMessage, expected => message.Exception.Message.Contains(expected)); } }
internal void AssertConnectionError <TException>(Http3ErrorCode expectedErrorCode, Action <Type, string[]> matchExpectedErrorMessage = null, params string[] expectedErrorMessage) where TException : Exception { var currentError = (Http3ErrorCode)MultiplexedConnectionContext.Error; if (currentError != expectedErrorCode) { throw new InvalidOperationException($"Expected error code {expectedErrorCode}, got {currentError}."); } matchExpectedErrorMessage?.Invoke(typeof(TException), expectedErrorMessage); }
public void Abort(ConnectionAbortedException abortReason, Http3ErrorCode errorCode) { // TODO - Should there be a check here to track abort state to avoid // running twice for a request? Log.Http3StreamAbort(_context.ConnectionId, errorCode, abortReason); _errorCodeFeature.Error = (long)errorCode; _frameWriter.Abort(abortReason); Input.Complete(abortReason); }
/// <summary> /// Aborts the connection with an error. /// </summary> /// <remarks> /// Used for e.g. I/O or connection-level frame parsing errors. /// </remarks> internal Exception Abort(Exception abortException) { // Only observe the first exception we get. Exception?firstException = Interlocked.CompareExchange(ref _abortException, abortException, null); if (firstException != null) { if (NetEventSource.Log.IsEnabled() && !ReferenceEquals(firstException, abortException)) { // Lost the race to set the field to another exception, so just trace this one. Trace($"{nameof(abortException)}=={abortException}"); } return(firstException); } // Stop sending requests to this connection. _pool.InvalidateHttp3Connection(this); Http3ErrorCode connectionResetErrorCode = (abortException as Http3ProtocolException)?.ErrorCode ?? Http3ErrorCode.InternalError; lock (SyncObj) { // Set _lastProcessedStreamId != -1 to make ShuttingDown = true. // It's possible GOAWAY is already being processed, in which case this would already be != -1. if (_lastProcessedStreamId == -1) { _lastProcessedStreamId = long.MaxValue; } // Abort the connection. This will cause all of our streams to abort on their next I/O. if (_connection != null && _connectionClosedTask == null) { _connectionClosedTask = _connection.CloseAsync((long)connectionResetErrorCode).AsTask(); } CancelWaiters(); CheckForShutdown(); } return(abortException); }
public void Abort(ConnectionAbortedException abortReason, Http3ErrorCode errorCode) { // TODO - Should there be a check here to track abort state to avoid // running twice for a request? Log.Http3StreamAbort(TraceIdentifier, errorCode, abortReason); _errorCodeFeature.Error = (long)errorCode; _frameWriter.Abort(abortReason); // Call _http3Output.Stop() prior to poisoning the request body stream or pipe to // ensure that an app that completes early due to the abort doesn't result in header frames being sent. _http3Output.Stop(); CancelRequestAbortedToken(); // Unblock the request body. PoisonBody(abortReason); RequestBodyPipe.Writer.Complete(abortReason); }
/// <summary> /// Accepts unidirectional streams (control, QPack, ...) from the server. /// </summary> private async Task AcceptStreamsAsync() { try { while (true) { ValueTask <QuicStream> streamTask; lock (SyncObj) { if (ShuttingDown) { return; } // No cancellation token is needed here; we expect the operation to cancel itself when _connection is disposed. streamTask = _connection !.AcceptInboundStreamAsync(CancellationToken.None); } QuicStream stream = await streamTask.ConfigureAwait(false); // This process is cleaned up when _connection is disposed, and errors are observed via Abort(). _ = ProcessServerStreamAsync(stream); } } catch (QuicException ex) when(ex.QuicError == QuicError.OperationAborted) { // Shutdown initiated by us, no need to abort. } catch (QuicException ex) when(ex.QuicError == QuicError.ConnectionAborted) { Debug.Assert(ex.ApplicationErrorCode.HasValue); Http3ErrorCode code = (Http3ErrorCode)ex.ApplicationErrorCode.Value; Abort(HttpProtocolException.CreateHttp3ConnectionException(code, SR.net_http_http3_connection_close)); } catch (Exception ex) { Abort(ex); } }
public void Abort(ConnectionAbortedException ex, Http3ErrorCode errorCode) { bool previousState; lock (_protocolSelectionLock) { previousState = _aborted; _aborted = true; } if (!previousState) { if (TryClose()) { SendGoAway(_highestOpenedStreamId); } _errorCodeFeature.Error = (long)errorCode; _multiplexedContext.Abort(ex); } }
public void Abort(ConnectionAbortedException ex, Http3ErrorCode errorCode) { bool previousState; lock (_protocolSelectionLock) { previousState = _aborted; _aborted = true; } if (!previousState) { _errorCodeFeature.Error = (long)errorCode; if (TryStopAcceptingStreams()) { SendGoAwayAsync(GetCurrentGoAwayStreamId()).Preserve(); } _multiplexedContext.Abort(ex); } }
public void Http3StreamAbort(string traceIdentifier, Http3ErrorCode error, ConnectionAbortedException abortReason) { }
internal static HttpProtocolException CreateHttp3ConnectionException(Http3ErrorCode protocolError, string?message = null) { message = SR.Format(message ?? SR.net_http_http3_connection_error, GetName(protocolError), ((int)protocolError).ToString("x")); return(new HttpProtocolException((long)protocolError, message, null)); }
public Http3StreamErrorException(string message, Http3ErrorCode errorCode) : base($"HTTP/3 stream error ({errorCode}): {message}") { ErrorCode = errorCode; }
public void Abort(ConnectionAbortedException ex, Http3ErrorCode errorCode) { }
protected Http3ProtocolException(string message, Http3ErrorCode errorCode) : base(message) { ErrorCode = errorCode; }
public Http3ConnectionErrorException(string message, Http3ErrorCode errorCode) : base($"HTTP/3 connection error ({errorCode}): {message}") { ErrorCode = errorCode; }
public void Abort(ConnectionAbortedException ex, Http3ErrorCode errorCode) { // TODO something with request aborted? }
public Http3ConnectionException(Http3ErrorCode errorCode) : base(SR.Format(SR.net_http_http3_connection_error, GetName(errorCode), ((long)errorCode).ToString("x")), errorCode) { }
internal void VerifyGoAway(Http3FrameWithPayload frame, long expectedLastStreamId, Http3ErrorCode expectedErrorCode) { Assert.Equal(Http3FrameType.GoAway, frame.Type); var payload = frame.Payload; Assert.True(VariableLengthIntegerHelper.TryRead(payload.Span, out var streamId, out var _)); Assert.Equal(expectedLastStreamId, streamId); }
internal async Task WaitForConnectionErrorAsync(bool ignoreNonGoAwayFrames, long expectedLastStreamId, Http3ErrorCode expectedErrorCode) { var frame = await _inboundControlStream.ReceiveFrameAsync(); if (ignoreNonGoAwayFrames) { while (frame.Type != Http3FrameType.GoAway) { frame = await _inboundControlStream.ReceiveFrameAsync(); } } VerifyGoAway(frame, expectedLastStreamId, expectedErrorCode); }
internal async Task WaitForConnectionErrorAsync <TException>(bool ignoreNonGoAwayFrames, long?expectedLastStreamId, Http3ErrorCode expectedErrorCode, params string[] expectedErrorMessage) where TException : Exception { var frame = await _inboundControlStream.ReceiveFrameAsync(); if (ignoreNonGoAwayFrames) { while (frame.Type != Http3FrameType.GoAway) { frame = await _inboundControlStream.ReceiveFrameAsync(); } } if (expectedLastStreamId != null) { VerifyGoAway(frame, expectedLastStreamId.GetValueOrDefault()); } Assert.Equal((Http3ErrorCode)expectedErrorCode, (Http3ErrorCode)MultiplexedConnectionContext.Error); if (expectedErrorMessage?.Length > 0) { var message = Assert.Single(LogMessages, m => m.Exception is TException); Assert.Contains(expectedErrorMessage, expected => message.Exception.Message.Contains(expected)); } }
public Http3ConnectionErrorException(string message, Http3ErrorCode errorCode) : base($"HTTP/3 connection error ({Http3Formatting.ToFormattedErrorCode(errorCode)}): {message}") { ErrorCode = errorCode; }
internal static HttpProtocolException CreateHttp3StreamException(Http3ErrorCode protocolError) { string message = SR.Format(SR.net_http_http3_stream_error, GetName(protocolError), ((int)protocolError).ToString("x")); return(new HttpProtocolException((long)protocolError, message, null)); }
protected Http3ProtocolException(SerializationInfo info, StreamingContext context) : base(info, context) { ErrorCode = (Http3ErrorCode)info.GetUInt32(nameof(ErrorCode)); }
public void Abort(ConnectionAbortedException abortReason, Http3ErrorCode errorCode) { AbortCore(abortReason, errorCode); }
protected static string GetName(Http3ErrorCode errorCode) => // These strings come from the H3 spec and should not be localized. errorCode switch {
internal async Task WaitForConnectionErrorAsync <TException>(bool ignoreNonGoAwayFrames, long?expectedLastStreamId, Http3ErrorCode expectedErrorCode, Action <Type, string[]> matchExpectedErrorMessage = null, params string[] expectedErrorMessage) where TException : Exception { await WaitForGoAwayAsync(ignoreNonGoAwayFrames, expectedLastStreamId); AssertConnectionError <TException>(expectedErrorCode, matchExpectedErrorMessage, expectedErrorMessage); // Verify HttpConnection.ProcessRequestsAsync has exited. #if IS_FUNCTIONAL_TESTS await _connectionTask.DefaultTimeout(); #else await _connectionTask; #endif }
internal async Task WaitForConnectionErrorAsync <TException>(bool ignoreNonGoAwayFrames, long?expectedLastStreamId, Http3ErrorCode expectedErrorCode, Action <Type, string[]> matchExpectedErrorMessage = null, params string[] expectedErrorMessage) where TException : Exception { var frame = await _inboundControlStream.ReceiveFrameAsync(); if (ignoreNonGoAwayFrames) { while (frame.Type != Http3FrameType.GoAway) { frame = await _inboundControlStream.ReceiveFrameAsync(); } } if (expectedLastStreamId != null) { VerifyGoAway(frame, expectedLastStreamId.GetValueOrDefault()); } AssertConnectionError <TException>(expectedErrorCode, matchExpectedErrorMessage, expectedErrorMessage); // Verify HttpConnection.ProcessRequestsAsync has exited. #if IS_FUNCTIONAL_TESTS await _connectionTask.DefaultTimeout(); #else await _connectionTask; #endif // Verify server-to-client control stream has completed. await _inboundControlStream.ReceiveEndAsync(); }