Skip to content

HTTP/3: Close unsupported unidirectional stream types #32160

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 27, 2021
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
3 changes: 3 additions & 0 deletions src/Servers/Kestrel/Core/src/CoreStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -689,4 +689,7 @@ For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?l
<data name="Http3ErrorControlStreamClientClosedInbound" xml:space="preserve">
<value>The client closed the connection control stream inbound to the server.</value>
</data>
<data name="Http3ControlStreamErrorUnsupportedType" xml:space="preserve">
<value>Stream type {type} is unsupported.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,6 @@ public async Task ProcessRequestAsync<TContext>(IHttpApplication<TContext> appli

switch (_headerType)
{
case -1:
return;
case ControlStreamTypeId:
if (!_context.StreamLifetimeHandler.OnInboundControlStream(this))
{
Expand Down Expand Up @@ -187,10 +185,14 @@ public async Task ProcessRequestAsync<TContext>(IHttpApplication<TContext> appli
await HandleEncodingDecodingTask();
break;
default:
// TODO Close the control stream as it's unexpected.
break;
// https://quicwg.org/base-drafts/draft-ietf-quic-http.html#section-6.2-6
throw new Http3StreamErrorException(CoreStrings.FormatHttp3ControlStreamErrorUnsupportedType(_headerType), Http3ErrorCode.StreamCreationError);
}
}
catch (Http3StreamErrorException ex)
{
Abort(new ConnectionAbortedException(ex.Message), ex.ErrorCode);
}
catch (Http3ConnectionErrorException ex)
{
_errorCodeFeature.Error = (long)ex.ErrorCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2385,5 +2385,39 @@ public Task HEADERS_Received_RequestLineLength_Error()

return HEADERS_Received_InvalidHeaderFields_StreamError(headers, CoreStrings.BadRequest_RequestLineTooLong, Http3ErrorCode.RequestRejected);
}

[Theory]
[InlineData(1)]
[InlineData(4)]
[InlineData(int.MaxValue)]
public async Task UnsupportedControlStreamType(int typeId)
{
await InitializeConnectionAsync(_noopApplication);

var outboundControlStream = await CreateControlStream().DefaultTimeout();
await outboundControlStream.SendSettingsAsync(new List<Http3PeerSetting>());

var inboundControlStream = await GetInboundControlStream();
await inboundControlStream.ExpectSettingsAsync();

// Create unsupported control stream
var invalidStream = await CreateControlStream(typeId).DefaultTimeout();
await invalidStream.WaitForStreamErrorAsync(
Http3ErrorCode.StreamCreationError,
CoreStrings.FormatHttp3ControlStreamErrorUnsupportedType(typeId)).DefaultTimeout();

// Connection is still alive and available for requests
var requestStream = await CreateRequestStream().DefaultTimeout();
await requestStream.SendHeadersAsync(new[]
{
new KeyValuePair<string, string>(HeaderNames.Path, "/"),
new KeyValuePair<string, string>(HeaderNames.Scheme, "http"),
new KeyValuePair<string, string>(HeaderNames.Method, "GET"),
new KeyValuePair<string, string>(HeaderNames.Authority, "localhost:80"),
}, endStream: true);

await requestStream.ExpectHeadersAsync().DefaultTimeout();
await requestStream.ExpectReceiveEndOfStream().DefaultTimeout();
}
}
}