}
catch (Exception e)
{
- Abort(e);
+ if (NetEventSource.IsEnabled) Trace($"ProcessIncomingFramesAsync: {e.Message}");
+
+ if (!_disposed)
+ {
+ Abort(e);
+ }
}
}
}
// If the connection has been aborted, then fail now instead of trying to send more data.
- if (IsAborted())
+ if (_disposed)
{
throw new IOException(SR.net_http_request_aborted);
}
_outgoingBuffer.Commit(FrameHeader.Size);
}
+ /// <summary>Abort all streams and cause further processing to fail.</summary>
+ /// <param name="abortException">Exception causing Abort to be called.</param>
private void Abort(Exception abortException)
{
// The connection has failed, e.g. failed IO or a connection-level frame error.
- // Abort all streams and cause further processing to fail.
- if (!IsAborted())
+ if (_abortException == null)
{
_abortException = abortException;
}
AbortStreams(0, abortException);
}
- private bool IsAborted()
- {
- return _disposed;
- }
-
/// <summary>Gets whether the connection exceeded any of the connection limits.</summary>
/// <param name="nowTicks">The current tick count. Passed in to amortize the cost of calling Environment.TickCount.</param>
/// <param name="connectionLifetime">How long a connection can be open to be considered reusable.</param>
private enum FrameFlags : byte
{
None = 0,
-
+
// Some frame types define bits differently. Define them all here for simplicity.
EndStream = 0b00000001,
{
lock (SyncObject)
{
- if (_disposed || _nextStream == MaxStreamId)
+ if (_nextStream == MaxStreamId || _disposed)
{
+ if (_abortException != null)
+ {
+ // Aborted because protocol error or IO.
+ throw new ObjectDisposedException(nameof(Http2Connection));
+ }
+
+ // We run out of IDs or we have race condition between receiving GOAWAY and processing requests.
// Throw a retryable request exception. This will cause retry logic to kick in
// and perform another connection attempt. The user should never see this exception.
throw new HttpRequestException(null, null, allowRetry: true);
{
if (!_httpStreams.Remove(http2Stream.StreamId, out Http2Stream removed))
{
- Debug.Fail("_httpStreams.Remove failed");
+ // Stream can be removed from background ProcessIncomingFramesAsync() when endOfStream is set
+ // or when we hit various error conditions in SendAsync() call.
+ // Skip logic below if stream was already removed.
+ return;
}
_concurrentStreams.AdjustCredit(1);