Skip to content
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

Configure ping in HTTP2 #40257

Merged
merged 35 commits into from
Aug 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
17ddbce
init
Jul 21, 2020
2afc76f
Http2 ping
Aug 3, 2020
c590b7c
Merge remote-tracking branch 'upstream/master' into jajahoda/httpping
Aug 3, 2020
eb37332
clean up
Aug 3, 2020
712479f
enable tests
Aug 3, 2020
95bc2f3
Fix mac build
Aug 3, 2020
de89629
Merge branch 'master' of github.com:dotnet/runtime into jajahoda/http…
Aug 3, 2020
b3e4b3d
Split HttpHandlerDefaults
Aug 4, 2020
e06f092
Merge branch 'master' of github.com:dotnet/runtime into jajahoda/http…
Aug 4, 2020
6e2f371
Merge remote-tracking branch 'origin/jajahoda/httpping' into jajahoda…
Aug 4, 2020
b7ed6ce
Fix mac build
Aug 4, 2020
20f44cf
Fix browser and test csproj
Aug 4, 2020
b684730
Apply PR comments
Aug 5, 2020
014c8d6
Merge remote-tracking branch 'upstream/master' into jajahoda/httpping
Aug 5, 2020
60a757d
Remove Http2KeepAlice class
Aug 5, 2020
886a2da
fix trace message
Aug 5, 2020
863f636
ProcessPingAck no longer return bool
Aug 5, 2020
a987919
Apply suggestions from code review
aik-jahoda Aug 6, 2020
b221f43
Add argument out of ramnge message
Aug 6, 2020
be468cd
Merge branch 'jajahoda/httpping' of github.com:aik-jahoda/runtime int…
Aug 6, 2020
db89b58
Apply PR comments
Aug 6, 2020
02785d6
SocketsHttpHandler setters
Aug 6, 2020
d354a29
Merge remote-tracking branch 'upstream/master' into jajahoda/httpping
Aug 7, 2020
b83cfc3
Update src/libraries/Common/tests/System/Net/Http/Http2LoopbackConnec…
aik-jahoda Aug 7, 2020
63e3d3f
Update src/libraries/System.Net.Http/src/Resources/Strings.resx
aik-jahoda Aug 7, 2020
258f1c4
Apply suggestions from code review
aik-jahoda Aug 7, 2020
2695f2e
PR comments
Aug 7, 2020
0ea45e8
Merge branch 'master' into jajahoda/httpping
ManickaP Aug 11, 2020
7078d8e
Addressed the last batch of PR feedback.
ManickaP Aug 11, 2020
9c1b6e7
Merge branch 'master' into jajahoda/httpping
ManickaP Aug 12, 2020
86c8413
Fixed KeepAlive test dependency on frame chronology.
ManickaP Aug 12, 2020
c10beb9
Fixed FW compilation.
ManickaP Aug 12, 2020
b9c6b33
Split and moved tests to theirs proper places.
ManickaP Aug 12, 2020
40e0e5c
More test fixing for super slow CI.
ManickaP Aug 12, 2020
3a753b7
Exception texts.
ManickaP Aug 13, 2020
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace System.Net.Http
/// Central repository for default values used in http handler settings. Not all settings are relevant
/// to or configurable by all handlers.
/// </summary>
internal static class HttpHandlerDefaults
internal static partial class HttpHandlerDefaults
{
public const int DefaultMaxAutomaticRedirections = 50;
public const int DefaultMaxConnectionsPerServer = int.MaxValue;
Expand Down
10 changes: 5 additions & 5 deletions src/libraries/Common/tests/System/Net/Http/Http2Frames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -344,17 +344,17 @@ public override string ToString()

public class PingFrame : Frame
{
public byte[] Data;
public long Data;

public PingFrame(byte[] data, FrameFlags flags, int streamId) :
public PingFrame(long data, FrameFlags flags, int streamId) :
base(8, FrameType.Ping, flags, streamId)
{
Data = data;
}

public static PingFrame ReadFrom(Frame header, ReadOnlySpan<byte> buffer)
{
byte[] data = buffer.ToArray();
long data = BinaryPrimitives.ReadInt64BigEndian(buffer);

return new PingFrame(data, header.Flags, header.StreamId);
}
Expand All @@ -364,12 +364,12 @@ public override void WriteTo(Span<byte> buffer)
base.WriteTo(buffer);
buffer = buffer.Slice(Frame.FrameHeaderLength, 8);

Data.CopyTo(buffer);
BinaryPrimitives.WriteInt64BigEndian(buffer, Data);
}

public override string ToString()
{
return base.ToString() + $"\nOpaque Data: {string.Join(", ", Data)}";
return base.ToString() + $"\nOpaque Data: {Data:X16}";
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class Http2LoopbackConnection : GenericLoopbackConnection
private Stream _connectionStream;
private TaskCompletionSource<bool> _ignoredSettingsAckPromise;
private bool _ignoreWindowUpdates;
private TaskCompletionSource<PingFrame> _expectPingFrame;
private readonly TimeSpan _timeout;
private int _lastStreamId;

Expand Down Expand Up @@ -186,6 +187,13 @@ private async Task<Frame> ReadFrameAsync(CancellationToken cancellationToken)
return await ReadFrameAsync(cancellationToken).ConfigureAwait(false);
}

if (_expectPingFrame != null && header.Type == FrameType.Ping)
{
_expectPingFrame.SetResult(PingFrame.ReadFrom(header, data));
_expectPingFrame = null;
return await ReadFrameAsync(cancellationToken).ConfigureAwait(false);
}

// Construct the correct frame type and return it.
switch (header.Type)
{
Expand Down Expand Up @@ -245,6 +253,15 @@ public void IgnoreWindowUpdates()
_ignoreWindowUpdates = true;
}

// Set up loopback server to expect PING frames among other frames.
// Once PING frame is read in ReadFrameAsync, the returned task is completed.
// The returned task is canceled in ReadPingAsync if no PING frame has been read so far.
public Task<PingFrame> ExpectPingFrameAsync()
{
_expectPingFrame ??= new TaskCompletionSource<PingFrame>();
return _expectPingFrame.Task;
}

public async Task ReadRstStreamAsync(int streamId)
{
Frame frame = await ReadFrameAsync(_timeout);
Expand Down Expand Up @@ -663,7 +680,7 @@ public async Task SendGoAway(int lastStreamId, ProtocolErrors errorCode = Protoc

public async Task PingPong()
{
byte[] pingData = new byte[8] { 1, 2, 3, 4, 50, 60, 70, 80 };
long pingData = BitConverter.ToInt64(new byte[8] { 1, 2, 3, 4, 50, 60, 70, 80 }, 0);
PingFrame ping = new PingFrame(pingData, FrameFlags.None, 0);
await WriteFrameAsync(ping).ConfigureAwait(false);
PingFrame pingAck = (PingFrame)await ReadFrameAsync(_timeout).ConfigureAwait(false);
Expand All @@ -675,6 +692,27 @@ public async Task PingPong()
Assert.Equal(pingData, pingAck.Data);
}

public async Task<PingFrame> ReadPingAsync(TimeSpan timeout)
{
_expectPingFrame?.TrySetCanceled();
_expectPingFrame = null;

Frame frame = await ReadFrameAsync(timeout).ConfigureAwait(false);
Assert.NotNull(frame);
Assert.Equal(FrameType.Ping, frame.Type);
Assert.Equal(0, frame.StreamId);
Assert.False(frame.AckFlag);
ManickaP marked this conversation as resolved.
Show resolved Hide resolved
Assert.Equal(8, frame.Length);

return Assert.IsAssignableFrom<PingFrame>(frame);
}

public async Task SendPingAckAsync(long payload)
{
PingFrame pingAck = new PingFrame(payload, FrameFlags.Ack, 0);
await WriteFrameAsync(pingAck).ConfigureAwait(false);
}

public async Task SendDefaultResponseHeadersAsync(int streamId)
{
byte[] headers = new byte[] { 0x88 }; // Encoding for ":status: 200"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
<Compile Include="$(CommonPath)\Interop\Windows\Crypt32\Interop.certificates_types.cs"
Link="Common\Interop\Windows\Crypt32\Interop.certificates_types.cs" />
<Compile Include="$(CommonPath)\Interop\Windows\Crypt32\Interop.certificates.cs"
Link="Common\Interop\Windows\Crypt32\Interop.certificates.cs" />
Link="Common\Interop\Windows\Crypt32\Interop.certificates.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.FormatMessage.cs"
Link="Common\Interop\Windows\Kernel32\Interop.FormatMessage.cs" />
Link="Common\Interop\Windows\Kernel32\Interop.FormatMessage.cs" />
<Compile Include="$(CommonPath)\Interop\Windows\Kernel32\Interop.GetModuleHandle.cs"
Link="Common\Interop\Windows\Kernel32\Interop.GetModuleHandle.cs" />
<Compile Include="$(CommonPath)\Interop\Windows\Interop.HRESULT_FROM_WIN32.cs"
Expand All @@ -56,7 +56,7 @@
<Compile Include="$(CommonPath)\System\Net\HttpKnownHeaderNames.cs"
Link="Common\System\Net\HttpKnownHeaderNames.cs" />
<Compile Include="$(CommonPath)\System\Net\HttpKnownHeaderNames.TryGetHeaderName.cs"
Link="Common\System\Net\HttpKnownHeaderNames.TryGetHeaderName.cs" />
Link="Common\System\Net\HttpKnownHeaderNames.TryGetHeaderName.cs" />
<Compile Include="$(CommonPath)System\Net\HttpStatusDescription.cs"
Link="Common\System\Net\Http\HttpStatusDescription.cs" />
<Compile Include="$(CommonPath)\System\Net\SecurityProtocol.cs"
Expand All @@ -74,7 +74,7 @@
<Compile Include="$(CommonPath)\System\Runtime\ExceptionServices\ExceptionStackTrace.cs"
Link="Common\System\Runtime\ExceptionServices\ExceptionStackTrace.cs" />
<Compile Include="$(CommonPath)\System\Threading\Tasks\RendezvousAwaitable.cs"
Link="Common\System\Threading\Tasks\RendezvousAwaitable.cs" />
Link="Common\System\Threading\Tasks\RendezvousAwaitable.cs" />
<Compile Include="$(CommonPath)System\Threading\Tasks\TaskToApm.cs"
Link="Common\System\Threading\Tasks\TaskToApm.cs" />
<Compile Include="System\Net\Http\NetEventSource.WinHttpHandler.cs" />
Expand Down
8 changes: 8 additions & 0 deletions src/libraries/System.Net.Http/ref/System.Net.Http.cs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,9 @@ public SocketsHttpHandler() { }
public System.Net.ICredentials? Credentials { get { throw null; } set { } }
public System.Net.ICredentials? DefaultProxyCredentials { get { throw null; } set { } }
public System.TimeSpan Expect100ContinueTimeout { get { throw null; } set { } }
public System.TimeSpan KeepAlivePingDelay { get { throw null; } set { } }
public System.TimeSpan KeepAlivePingTimeout { get { throw null; } set { } }
public HttpKeepAlivePingPolicy KeepAlivePingPolicy { get { throw null; } set { } }
public int MaxAutomaticRedirections { get { throw null; } set { } }
public int MaxConnectionsPerServer { get { throw null; } set { } }
public int MaxResponseDrainSize { get { throw null; } set { } }
Expand All @@ -369,6 +372,11 @@ protected override void Dispose(bool disposing) { }
protected internal override System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage> SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { throw null; }
public bool EnableMultipleHttp2Connections { get { throw null; } set { } }
}
public enum HttpKeepAlivePingPolicy
{
WithActiveRequests,
Always
}
public partial class StreamContent : System.Net.Http.HttpContent
{
public StreamContent(System.IO.Stream content) { }
Expand Down
57 changes: 30 additions & 27 deletions src/libraries/System.Net.Http/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema

Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes

The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.

Example:

... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
Expand All @@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple

There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the

Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not

The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can

Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.

mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.

mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
Expand Down Expand Up @@ -264,6 +264,9 @@
<data name="net_http_value_must_be_greater_than" xml:space="preserve">
<value>The specified value must be greater than {0}.</value>
</data>
<data name="net_http_value_must_be_greater_than_or_equal" xml:space="preserve">
<value>The specified value '{0}' must be greater than or equal to '{1}'.</value>
</data>
<data name="MailHeaderFieldInvalidCharacter" xml:space="preserve">
<value>An invalid character was found in the mail header: '{0}'.</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions src/libraries/System.Net.Http/src/System.Net.Http.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
</ItemGroup>
<!-- SocketsHttpHandler implementation -->
<ItemGroup Condition="'$(TargetsBrowser)' != 'true'">
<Compile Include="System\Net\Http\HttpHandlerDefaults.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\AuthenticationHelper.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\AuthenticationHelper.Digest.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\AuthenticationHelper.NtAuth.cs" />
Expand Down Expand Up @@ -168,6 +169,7 @@
<Compile Include="System\Net\Http\SocketsHttpHandler\HttpContentReadStream.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\HttpContentStream.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\HttpContentWriteStream.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\HttpKeepAlivePingPolicy.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\IHttpTrace.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\IMultiWebProxy.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\MultiProxy.cs" />
Expand Down Expand Up @@ -670,6 +672,7 @@
Link="Common\System\Text\ValueStringBuilder.cs" />
<Compile Include="$(CommonPath)System\Threading\Tasks\TaskToApm.cs"
Link="System\System\Threading\Tasks\TaskToApm.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\HttpKeepAlivePingPolicy.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\HttpNoProxy.cs" />
<Compile Include="System\Net\Http\BrowserHttpHandler\SystemProxyInfo.Browser.cs" />
<Compile Include="System\Net\Http\BrowserHttpHandler\SocketsHttpHandler.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,25 @@ public TimeSpan Expect100ContinueTimeout
set => throw new PlatformNotSupportedException();
}

public TimeSpan KeepAlivePingDelay
{
get => throw new PlatformNotSupportedException();
set => throw new PlatformNotSupportedException();
}

public TimeSpan KeepAlivePingTimeout
{
get => throw new PlatformNotSupportedException();
set => throw new PlatformNotSupportedException();
}


public HttpKeepAlivePingPolicy KeepAlivePingPolicy
{
get => throw new PlatformNotSupportedException();
set => throw new PlatformNotSupportedException();
}

public ConnectionFactory? ConnectionFactory
{
get => throw new PlatformNotSupportedException();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Threading;

namespace System.Net.Http
{
/// <summary>
/// Additional default values used used only in this assembly.
/// </summary>
internal static partial class HttpHandlerDefaults
{
public static readonly TimeSpan DefaultKeepAlivePingTimeout = TimeSpan.FromSeconds(20);
aik-jahoda marked this conversation as resolved.
Show resolved Hide resolved
public static readonly TimeSpan DefaultKeepAlivePingDelay = Timeout.InfiniteTimeSpan;
public const HttpKeepAlivePingPolicy DefaultKeepAlivePingPolicy = HttpKeepAlivePingPolicy.Always;
}
}
Loading