diff --git a/src/Kestrel.Core/Internal/Http2/Http2Connection.cs b/src/Kestrel.Core/Internal/Http2/Http2Connection.cs index 3622686dfd..269cc034e2 100644 --- a/src/Kestrel.Core/Internal/Http2/Http2Connection.cs +++ b/src/Kestrel.Core/Internal/Http2/Http2Connection.cs @@ -413,6 +413,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2 throw new Http2ConnectionErrorException(Http2ErrorCode.FRAME_SIZE_ERROR); } + if ((_incomingFrame.PingFlags & Http2PingFrameFlags.ACK) == Http2PingFrameFlags.ACK) + { + return Task.CompletedTask; + } + return _frameWriter.WritePingAsync(Http2PingFrameFlags.ACK, _incomingFrame.Payload); } diff --git a/test/Kestrel.Core.Tests/Http2ConnectionTests.cs b/test/Kestrel.Core.Tests/Http2ConnectionTests.cs index 7b3a96221a..0de04f62df 100644 --- a/test/Kestrel.Core.Tests/Http2ConnectionTests.cs +++ b/test/Kestrel.Core.Tests/Http2ConnectionTests.cs @@ -923,11 +923,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests } [Fact] - public async Task PING_Received_Sends_ACK() + public async Task PING_Received_SendsACK() { await InitializeConnectionAsync(_noopApplication); - await SendPingAsync(); + await SendPingAsync(Http2PingFrameFlags.NONE); await ExpectAsync(Http2FrameType.PING, withLength: 8, withFlags: (byte)Http2PingFrameFlags.ACK, @@ -936,13 +936,23 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests await StopConnectionAsync(expectedLastStreamId: 0, ignoreNonGoAwayFrames: false); } + [Fact] + public async Task PING_Received_WithACK_DoesNotSendACK() + { + await InitializeConnectionAsync(_noopApplication); + + await SendPingAsync(Http2PingFrameFlags.ACK); + + await StopConnectionAsync(expectedLastStreamId: 0, ignoreNonGoAwayFrames: false); + } + [Fact] public async Task PING_Received_InterleavedWithHeaders_ConnectionError() { await InitializeConnectionAsync(_noopApplication); await SendHeadersAsync(1, Http2HeadersFrameFlags.NONE, _browserRequestHeaders); - await SendPingAsync(); + await SendPingAsync(Http2PingFrameFlags.NONE); await WaitForConnectionErrorAsync(expectedLastStreamId: 0, expectedErrorCode: Http2ErrorCode.PROTOCOL_ERROR, ignoreNonGoAwayFrames: false); } @@ -1160,7 +1170,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests await SendUnknownFrameTypeAsync(streamId: 1); // Check that the connection is still alive - await SendPingAsync(); + await SendPingAsync(Http2PingFrameFlags.NONE); await ExpectAsync(Http2FrameType.PING, withLength: 8, withFlags: (byte)Http2PingFrameFlags.ACK, @@ -1502,10 +1512,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests return SendAsync(frame.Raw); } - private Task SendPingAsync() + private Task SendPingAsync(Http2PingFrameFlags flags) { var pingFrame = new Http2Frame(); - pingFrame.PreparePing(Http2PingFrameFlags.NONE); + pingFrame.PreparePing(flags); return SendAsync(pingFrame.Raw); }