Skip to content

Commit bc69abc

Browse files
committed
Infrastructure cleanup
1 parent b0d7fc9 commit bc69abc

17 files changed

+395
-239
lines changed
Lines changed: 77 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4-
using System;
54
using System.Threading.Tasks;
6-
using http2cat;
7-
using Microsoft.AspNetCore.Hosting;
5+
using Microsoft.AspNetCore.Http2Cat;
86
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
97
using Microsoft.AspNetCore.Testing;
108
using Microsoft.Extensions.Hosting;
@@ -27,62 +25,53 @@ public async Task ConnectionClose_NoOSSupport_NoGoAway()
2725
return Task.FromResult(0);
2826
});
2927

30-
using var host = new HostBuilder()
31-
.ConfigureServices(services =>
28+
await new HostBuilder()
29+
.UseHttp2Cat(address, async h2Connection =>
3230
{
33-
services.UseHttp2Cat(options =>
34-
{
35-
options.Url = address;
36-
options.Scenaro = async (http2Utilities, logger) =>
37-
{
38-
await http2Utilities.InitializeConnectionAsync();
31+
await h2Connection.InitializeConnectionAsync();
3932

40-
logger.LogInformation("Initialized http2 connection. Starting stream 1.");
33+
h2Connection.Logger.LogInformation("Initialized http2 connection. Starting stream 1.");
4134

42-
await http2Utilities.StartStreamAsync(1, Http2Utilities._browserRequestHeaders, endStream: true);
35+
await h2Connection.StartStreamAsync(1, Http2Utilities.BrowserRequestHeaders, endStream: true);
4336

44-
var headersFrame = await http2Utilities.ReceiveFrameAsync();
37+
var headersFrame = await h2Connection.ReceiveFrameAsync();
4538

46-
Assert.Equal(Http2FrameType.HEADERS, headersFrame.Type);
47-
Assert.True((headersFrame.Flags & (byte)Http2HeadersFrameFlags.END_HEADERS) != 0);
48-
Assert.True((headersFrame.Flags & (byte)Http2HeadersFrameFlags.END_STREAM) != 0);
39+
Assert.Equal(Http2FrameType.HEADERS, headersFrame.Type);
40+
Assert.True((headersFrame.Flags & (byte)Http2HeadersFrameFlags.END_HEADERS) != 0);
41+
Assert.True((headersFrame.Flags & (byte)Http2HeadersFrameFlags.END_STREAM) != 0);
4942

50-
logger.LogInformation("Received headers in a single frame.");
43+
h2Connection.Logger.LogInformation("Received headers in a single frame.");
5144

52-
var decodedHeaders = http2Utilities.DecodeHeaders(headersFrame);
45+
var decodedHeaders = h2Connection.DecodeHeaders(headersFrame);
5346

54-
// HTTP/2 filters out the connection header
55-
Assert.False(decodedHeaders.ContainsKey(HeaderNames.Connection));
56-
Assert.Equal("200", decodedHeaders[HeaderNames.Status]);
47+
// HTTP/2 filters out the connection header
48+
Assert.False(decodedHeaders.ContainsKey(HeaderNames.Connection));
49+
Assert.Equal("200", decodedHeaders[HeaderNames.Status]);
5750

58-
// Send and receive a second request to ensure there is no GoAway frame on the wire yet.
51+
// Send and receive a second request to ensure there is no GoAway frame on the wire yet.
5952

60-
await http2Utilities.StartStreamAsync(3, Http2Utilities._browserRequestHeaders, endStream: true);
53+
await h2Connection.StartStreamAsync(3, Http2Utilities.BrowserRequestHeaders, endStream: true);
6154

62-
headersFrame = await http2Utilities.ReceiveFrameAsync();
55+
headersFrame = await h2Connection.ReceiveFrameAsync();
6356

64-
Assert.Equal(Http2FrameType.HEADERS, headersFrame.Type);
65-
Assert.True((headersFrame.Flags & (byte)Http2HeadersFrameFlags.END_HEADERS) != 0);
66-
Assert.True((headersFrame.Flags & (byte)Http2HeadersFrameFlags.END_STREAM) != 0);
57+
Assert.Equal(Http2FrameType.HEADERS, headersFrame.Type);
58+
Assert.True((headersFrame.Flags & (byte)Http2HeadersFrameFlags.END_HEADERS) != 0);
59+
Assert.True((headersFrame.Flags & (byte)Http2HeadersFrameFlags.END_STREAM) != 0);
6760

68-
logger.LogInformation("Received headers in a single frame.");
61+
h2Connection.Logger.LogInformation("Received headers in a single frame.");
6962

70-
http2Utilities.ResetHeaders();
71-
decodedHeaders = http2Utilities.DecodeHeaders(headersFrame);
63+
h2Connection.ResetHeaders();
64+
decodedHeaders = h2Connection.DecodeHeaders(headersFrame);
7265

73-
// HTTP/2 filters out the connection header
74-
Assert.False(decodedHeaders.ContainsKey(HeaderNames.Connection));
75-
Assert.Equal("200", decodedHeaders[HeaderNames.Status]);
66+
// HTTP/2 filters out the connection header
67+
Assert.False(decodedHeaders.ContainsKey(HeaderNames.Connection));
68+
Assert.Equal("200", decodedHeaders[HeaderNames.Status]);
7669

77-
await http2Utilities.StopConnectionAsync(expectedLastStreamId: 1, ignoreNonGoAwayFrames: false);
70+
await h2Connection.StopConnectionAsync(expectedLastStreamId: 1, ignoreNonGoAwayFrames: false);
7871

79-
logger.LogInformation("Connection stopped.");
80-
};
81-
});
72+
h2Connection.Logger.LogInformation("Connection stopped.");
8273
})
83-
.Build();
84-
85-
await host.RunHttp2CatAsync();
74+
.Build().RunAsync();
8675
}
8776

8877
[ConditionalFact]
@@ -95,64 +84,55 @@ public async Task ConnectionClose_OSSupport_SendsGoAway()
9584
return Task.FromResult(0);
9685
});
9786

98-
using var host = new HostBuilder()
99-
.ConfigureServices(services =>
87+
await new HostBuilder()
88+
.UseHttp2Cat(address, async h2Connection =>
10089
{
101-
services.UseHttp2Cat(options =>
102-
{
103-
options.Url = address;
104-
options.Scenaro = async (http2Utilities, logger) =>
105-
{
106-
await http2Utilities.InitializeConnectionAsync();
107-
108-
logger.LogInformation("Initialized http2 connection. Starting stream 1.");
109-
110-
await http2Utilities.StartStreamAsync(1, Http2Utilities._browserRequestHeaders, endStream: true);
111-
112-
var goAwayFrame = await http2Utilities.ReceiveFrameAsync();
113-
http2Utilities.VerifyGoAway(goAwayFrame, int.MaxValue, Http2ErrorCode.NO_ERROR);
114-
115-
var headersFrame = await http2Utilities.ReceiveFrameAsync();
116-
117-
Assert.Equal(Http2FrameType.HEADERS, headersFrame.Type);
118-
Assert.Equal(Http2HeadersFrameFlags.END_HEADERS, headersFrame.HeadersFlags);
119-
120-
logger.LogInformation("Received headers in a single frame.");
121-
122-
var decodedHeaders = http2Utilities.DecodeHeaders(headersFrame);
123-
124-
// HTTP/2 filters out the connection header
125-
Assert.False(decodedHeaders.ContainsKey(HeaderNames.Connection));
126-
Assert.Equal("200", decodedHeaders[HeaderNames.Status]);
127-
128-
var dataFrame = await http2Utilities.ReceiveFrameAsync();
129-
Assert.Equal(Http2FrameType.DATA, dataFrame.Type);
130-
Assert.Equal(Http2DataFrameFlags.END_STREAM, dataFrame.DataFlags);
131-
Assert.Equal(0, dataFrame.PayloadLength);
132-
133-
// TODO: Why doesn't HttpSys send a final GoAway or close the connection?
134-
// https://tools.ietf.org/html/rfc7540#section-6.8
135-
// A server that is attempting to gracefully shut down a
136-
// connection SHOULD send an initial GOAWAY frame with the last stream
137-
// identifier set to 2^31-1 and a NO_ERROR code. This signals to the
138-
// client that a shutdown is imminent and that initiating further
139-
// requests is prohibited. After allowing time for any in-flight stream
140-
// creation (at least one round-trip time), the server can send another
141-
// GOAWAY frame with an updated last stream identifier. This ensures
142-
// that a connection can be cleanly shut down without losing requests.
143-
//
144-
// await http2Utilities.StopConnectionAsync(expectedLastStreamId: 1, ignoreNonGoAwayFrames: false);
145-
// or
146-
// await http2Utilities.SendGoAwayAsync();
147-
// await http2Utilities.WaitForConnectionStopAsync(expectedLastStreamId: 1, ignoreNonGoAwayFrames: false);
148-
149-
logger.LogInformation("Connection stopped.");
150-
};
151-
});
152-
})
153-
.Build();
90+
await h2Connection.InitializeConnectionAsync();
91+
92+
h2Connection.Logger.LogInformation("Initialized http2 connection. Starting stream 1.");
93+
94+
await h2Connection.StartStreamAsync(1, Http2Utilities.BrowserRequestHeaders, endStream: true);
95+
96+
var goAwayFrame = await h2Connection.ReceiveFrameAsync();
97+
h2Connection.VerifyGoAway(goAwayFrame, int.MaxValue, Http2ErrorCode.NO_ERROR);
98+
99+
var headersFrame = await h2Connection.ReceiveFrameAsync();
100+
101+
Assert.Equal(Http2FrameType.HEADERS, headersFrame.Type);
102+
Assert.Equal(Http2HeadersFrameFlags.END_HEADERS, headersFrame.HeadersFlags);
154103

155-
await host.RunHttp2CatAsync();
104+
h2Connection.Logger.LogInformation("Received headers in a single frame.");
105+
106+
var decodedHeaders = h2Connection.DecodeHeaders(headersFrame);
107+
108+
// HTTP/2 filters out the connection header
109+
Assert.False(decodedHeaders.ContainsKey(HeaderNames.Connection));
110+
Assert.Equal("200", decodedHeaders[HeaderNames.Status]);
111+
112+
var dataFrame = await h2Connection.ReceiveFrameAsync();
113+
Assert.Equal(Http2FrameType.DATA, dataFrame.Type);
114+
Assert.Equal(Http2DataFrameFlags.END_STREAM, dataFrame.DataFlags);
115+
Assert.Equal(0, dataFrame.PayloadLength);
116+
117+
// TODO: Why doesn't HttpSys send a final GoAway or close the connection?
118+
// https://tools.ietf.org/html/rfc7540#section-6.8
119+
// A server that is attempting to gracefully shut down a
120+
// connection SHOULD send an initial GOAWAY frame with the last stream
121+
// identifier set to 2^31-1 and a NO_ERROR code. This signals to the
122+
// client that a shutdown is imminent and that initiating further
123+
// requests is prohibited. After allowing time for any in-flight stream
124+
// creation (at least one round-trip time), the server can send another
125+
// GOAWAY frame with an updated last stream identifier. This ensures
126+
// that a connection can be cleanly shut down without losing requests.
127+
//
128+
// await h2Connection.StopConnectionAsync(expectedLastStreamId: 1, ignoreNonGoAwayFrames: false);
129+
// or
130+
// await h2Connection.SendGoAwayAsync();
131+
// await h2Connection.WaitForConnectionStopAsync(expectedLastStreamId: 1, ignoreNonGoAwayFrames: false);
132+
133+
h2Connection.Logger.LogInformation("Connection stopped.");
134+
})
135+
.Build().RunAsync();
156136
}
157137
}
158138
}

src/Servers/HttpSys/test/FunctionalTests/Microsoft.AspNetCore.Server.HttpSys.FunctionalTests.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
</ItemGroup>
3535

3636
<ItemGroup>
37-
<EmbeddedResource Include="$(RepoRoot)src\Servers\Kestrel\Core\src\CoreStrings.resx" Link="Shared\CoreStrings.resx">
38-
<ManifestResourceName>Microsoft.AspNetCore.Server.Kestrel.Core.CoreStrings</ManifestResourceName>
37+
<EmbeddedResource Include="$(SharedSourceRoot)ServerInfrastructure\SharedStrings.resx" Link="Shared\SharedStrings.resx">
38+
<ManifestResourceName>Microsoft.AspNetCore.Server.SharedStrings</ManifestResourceName>
3939
<Generator></Generator>
4040
</EmbeddedResource>
4141
<EmbeddedResource Include="$(SharedSourceRoot)Http2\SR.resx" Link="Shared\Http2\SR.resx">

src/Servers/Kestrel/Core/src/Microsoft.AspNetCore.Server.Kestrel.Core.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
<EmbeddedResource Update="CoreStrings.resx">
3737
<Generator></Generator>
3838
</EmbeddedResource>
39+
<EmbeddedResource Include="$(SharedSourceRoot)ServerInfrastructure\SharedStrings.resx" Link="Shared\SharedStrings.resx">
40+
<ManifestResourceName>Microsoft.AspNetCore.Server.SharedStrings</ManifestResourceName>
41+
<Generator></Generator>
42+
</EmbeddedResource>
3943
<EmbeddedResource Include="$(SharedSourceRoot)Http2\SR.resx" Link="Shared\Http2\SR.resx">
4044
<ManifestResourceName>System.Net.Http.SR</ManifestResourceName>
4145
<Generator></Generator>

src/Servers/Kestrel/samples/http2cat/Program.cs

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Diagnostics;
55
using System.Text;
66
using System.Threading.Tasks;
7+
using Microsoft.AspNetCore.Http2Cat;
78
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
89
using Microsoft.Extensions.Hosting;
910
using Microsoft.Extensions.Logging;
@@ -19,69 +20,62 @@ static async Task Main(string[] args)
1920
{
2021
loggingBuilder.AddConsole();
2122
})
22-
.ConfigureServices(services =>
23-
{
24-
services.UseHttp2Cat(options =>
25-
{
26-
options.Url = "https://localhost:5001";
27-
options.Scenaro = RunTestCase;
28-
});
29-
})
23+
.UseHttp2Cat("https://localhost:5001", RunTestCase)
3024
.Build();
3125

32-
await host.RunHttp2CatAsync();
26+
await host.RunAsync();
3327
}
3428

35-
public static async Task RunTestCase(Http2Utilities http2Utilities, ILogger logger)
29+
public static async Task RunTestCase(Http2Utilities h2Connection)
3630
{
37-
await http2Utilities.InitializeConnectionAsync();
31+
await h2Connection.InitializeConnectionAsync();
3832

39-
logger.LogInformation("Initialized http2 connection. Starting stream 1.");
33+
h2Connection.Logger.LogInformation("Initialized http2 connection. Starting stream 1.");
4034

41-
await http2Utilities.StartStreamAsync(1, Http2Utilities._browserRequestHeaders, endStream: true);
35+
await h2Connection.StartStreamAsync(1, Http2Utilities.BrowserRequestHeaders, endStream: true);
4236

43-
var headersFrame = await http2Utilities.ReceiveFrameAsync();
37+
var headersFrame = await h2Connection.ReceiveFrameAsync();
4438

45-
Trace.Assert(headersFrame.Type == Http2FrameType.HEADERS);
39+
Trace.Assert(headersFrame.Type == Http2FrameType.HEADERS, headersFrame.Type.ToString());
4640
Trace.Assert((headersFrame.Flags & (byte)Http2HeadersFrameFlags.END_HEADERS) != 0);
4741
Trace.Assert((headersFrame.Flags & (byte)Http2HeadersFrameFlags.END_STREAM) == 0);
4842

49-
logger.LogInformation("Received headers in a single frame.");
43+
h2Connection.Logger.LogInformation("Received headers in a single frame.");
5044

51-
var decodedHeaders = http2Utilities.DecodeHeaders(headersFrame);
45+
var decodedHeaders = h2Connection.DecodeHeaders(headersFrame);
5246

5347
foreach (var header in decodedHeaders)
5448
{
55-
logger.LogInformation($"{header.Key}: {header.Value}");
49+
h2Connection.Logger.LogInformation($"{header.Key}: {header.Value}");
5650
}
5751

58-
var dataFrame = await http2Utilities.ReceiveFrameAsync();
52+
var dataFrame = await h2Connection.ReceiveFrameAsync();
5953

6054
Trace.Assert(dataFrame.Type == Http2FrameType.DATA);
6155
Trace.Assert((dataFrame.Flags & (byte)Http2DataFrameFlags.END_STREAM) == 0);
6256

63-
logger.LogInformation("Received data in a single frame.");
57+
h2Connection.Logger.LogInformation("Received data in a single frame.");
6458

65-
logger.LogInformation(Encoding.UTF8.GetString(dataFrame.Payload.ToArray()));
59+
h2Connection.Logger.LogInformation(Encoding.UTF8.GetString(dataFrame.Payload.ToArray()));
6660

67-
var trailersFrame = await http2Utilities.ReceiveFrameAsync();
61+
var trailersFrame = await h2Connection.ReceiveFrameAsync();
6862

6963
Trace.Assert(trailersFrame.Type == Http2FrameType.HEADERS);
7064
Trace.Assert((trailersFrame.Flags & (byte)Http2DataFrameFlags.END_STREAM) == 1);
7165

72-
logger.LogInformation("Received trailers in a single frame.");
66+
h2Connection.Logger.LogInformation("Received trailers in a single frame.");
7367

74-
http2Utilities.ResetHeaders();
75-
var decodedTrailers = http2Utilities.DecodeHeaders(trailersFrame);
68+
h2Connection.ResetHeaders();
69+
var decodedTrailers = h2Connection.DecodeHeaders(trailersFrame);
7670

77-
foreach (var header in decodedHeaders)
71+
foreach (var header in decodedTrailers)
7872
{
79-
logger.LogInformation($"{header.Key}: {header.Value}");
73+
h2Connection.Logger.LogInformation($"{header.Key}: {header.Value}");
8074
}
8175

82-
await http2Utilities.StopConnectionAsync(expectedLastStreamId: 1, ignoreNonGoAwayFrames: false);
76+
await h2Connection.StopConnectionAsync(expectedLastStreamId: 1, ignoreNonGoAwayFrames: false);
8377

84-
logger.LogInformation("Connection stopped.");
78+
h2Connection.Logger.LogInformation("Connection stopped.");
8579
}
8680
}
8781
}

src/Servers/Kestrel/samples/http2cat/http2cat.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
</ItemGroup>
2424

2525
<ItemGroup>
26-
<EmbeddedResource Include="..\..\Core\src\CoreStrings.resx" Link="Shared\CoreStrings.resx">
27-
<ManifestResourceName>Microsoft.AspNetCore.Server.Kestrel.Core.CoreStrings</ManifestResourceName>
26+
<EmbeddedResource Include="$(SharedSourceRoot)ServerInfrastructure\SharedStrings.resx" Link="Shared\SharedStrings.resx">
27+
<ManifestResourceName>Microsoft.AspNetCore.Server.SharedStrings</ManifestResourceName>
2828
<Generator></Generator>
2929
</EmbeddedResource>
3030
<EmbeddedResource Include="$(SharedSourceRoot)Http2\SR.resx" Link="Shared\Http2\SR.resx">

0 commit comments

Comments
 (0)