Merge remote-tracking branch 'upstream/release/5.0-rc2' into stage1-rtm+1

This commit is contained in:
Matt Mitchell 2020-09-11 08:56:49 -07:00
Родитель bd3d2f17ca 0dbdb83b82
Коммит afed25705d
17 изменённых файлов: 394 добавлений и 161 удалений

Просмотреть файл

@ -10,61 +10,61 @@
</Dependency>
</ProductDependencies>
<ToolsetDependencies>
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.20453.7">
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.20459.8">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>16b71a2f216c3c5be5860977c4cb03a95ee2f0e3</Sha>
<Sha>91470b0b14ba016c1fb78211b12775287c17b34e</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="5.0.0-beta.20453.7">
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="5.0.0-beta.20459.8">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>16b71a2f216c3c5be5860977c4cb03a95ee2f0e3</Sha>
<Sha>91470b0b14ba016c1fb78211b12775287c17b34e</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.ApiCompat" Version="5.0.0-beta.20453.7">
<Dependency Name="Microsoft.DotNet.ApiCompat" Version="5.0.0-beta.20459.8">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>16b71a2f216c3c5be5860977c4cb03a95ee2f0e3</Sha>
<Sha>91470b0b14ba016c1fb78211b12775287c17b34e</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.GenAPI" Version="5.0.0-beta.20453.7">
<Dependency Name="Microsoft.DotNet.GenAPI" Version="5.0.0-beta.20459.8">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>16b71a2f216c3c5be5860977c4cb03a95ee2f0e3</Sha>
<Sha>91470b0b14ba016c1fb78211b12775287c17b34e</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.GenFacades" Version="5.0.0-beta.20453.7">
<Dependency Name="Microsoft.DotNet.GenFacades" Version="5.0.0-beta.20459.8">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>16b71a2f216c3c5be5860977c4cb03a95ee2f0e3</Sha>
<Sha>91470b0b14ba016c1fb78211b12775287c17b34e</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.XUnitExtensions" Version="5.0.0-beta.20453.7">
<Dependency Name="Microsoft.DotNet.XUnitExtensions" Version="5.0.0-beta.20459.8">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>16b71a2f216c3c5be5860977c4cb03a95ee2f0e3</Sha>
<Sha>91470b0b14ba016c1fb78211b12775287c17b34e</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.XUnitConsoleRunner" Version="2.5.1-beta.20453.7">
<Dependency Name="Microsoft.DotNet.XUnitConsoleRunner" Version="2.5.1-beta.20459.8">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>16b71a2f216c3c5be5860977c4cb03a95ee2f0e3</Sha>
<Sha>91470b0b14ba016c1fb78211b12775287c17b34e</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Build.Tasks.Packaging" Version="5.0.0-beta.20453.7">
<Dependency Name="Microsoft.DotNet.Build.Tasks.Packaging" Version="5.0.0-beta.20459.8">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>16b71a2f216c3c5be5860977c4cb03a95ee2f0e3</Sha>
<Sha>91470b0b14ba016c1fb78211b12775287c17b34e</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.CodeAnalysis" Version="5.0.0-beta.20453.7">
<Dependency Name="Microsoft.DotNet.CodeAnalysis" Version="5.0.0-beta.20459.8">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>16b71a2f216c3c5be5860977c4cb03a95ee2f0e3</Sha>
<Sha>91470b0b14ba016c1fb78211b12775287c17b34e</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk" Version="5.0.0-beta.20453.7">
<Dependency Name="Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk" Version="5.0.0-beta.20459.8">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>16b71a2f216c3c5be5860977c4cb03a95ee2f0e3</Sha>
<Sha>91470b0b14ba016c1fb78211b12775287c17b34e</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.RemoteExecutor" Version="5.0.0-beta.20453.7">
<Dependency Name="Microsoft.DotNet.RemoteExecutor" Version="5.0.0-beta.20459.8">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>16b71a2f216c3c5be5860977c4cb03a95ee2f0e3</Sha>
<Sha>91470b0b14ba016c1fb78211b12775287c17b34e</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Build.Tasks.Feed" Version="5.0.0-beta.20453.7">
<Dependency Name="Microsoft.DotNet.Build.Tasks.Feed" Version="5.0.0-beta.20459.8">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>16b71a2f216c3c5be5860977c4cb03a95ee2f0e3</Sha>
<Sha>91470b0b14ba016c1fb78211b12775287c17b34e</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.VersionTools.Tasks" Version="5.0.0-beta.20453.7">
<Dependency Name="Microsoft.DotNet.VersionTools.Tasks" Version="5.0.0-beta.20459.8">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>16b71a2f216c3c5be5860977c4cb03a95ee2f0e3</Sha>
<Sha>91470b0b14ba016c1fb78211b12775287c17b34e</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Build.Tasks.SharedFramework.Sdk" Version="5.0.0-beta.20453.7">
<Dependency Name="Microsoft.DotNet.Build.Tasks.SharedFramework.Sdk" Version="5.0.0-beta.20459.8">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>16b71a2f216c3c5be5860977c4cb03a95ee2f0e3</Sha>
<Sha>91470b0b14ba016c1fb78211b12775287c17b34e</Sha>
</Dependency>
<Dependency Name="optimization.windows_nt-x64.IBC.CoreFx" Version="99.99.99-master-20200806.6">
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-optimization</Uri>

Просмотреть файл

@ -50,16 +50,16 @@
<!-- Pin compiler version to workaround: https://github.com/dotnet/runtime/issues/41100 -->
<MicrosoftNetCompilersToolsetVersion>3.8.0-2.20403.2</MicrosoftNetCompilersToolsetVersion>
<!-- Arcade dependencies -->
<MicrosoftDotNetApiCompatVersion>5.0.0-beta.20453.7</MicrosoftDotNetApiCompatVersion>
<MicrosoftDotNetBuildTasksFeedVersion>5.0.0-beta.20453.7</MicrosoftDotNetBuildTasksFeedVersion>
<MicrosoftDotNetCodeAnalysisVersion>5.0.0-beta.20453.7</MicrosoftDotNetCodeAnalysisVersion>
<MicrosoftDotNetGenAPIVersion>5.0.0-beta.20453.7</MicrosoftDotNetGenAPIVersion>
<MicrosoftDotNetGenFacadesVersion>5.0.0-beta.20453.7</MicrosoftDotNetGenFacadesVersion>
<MicrosoftDotNetXUnitExtensionsVersion>5.0.0-beta.20453.7</MicrosoftDotNetXUnitExtensionsVersion>
<MicrosoftDotNetXUnitConsoleRunnerVersion>2.5.1-beta.20453.7</MicrosoftDotNetXUnitConsoleRunnerVersion>
<MicrosoftDotNetBuildTasksPackagingVersion>5.0.0-beta.20453.7</MicrosoftDotNetBuildTasksPackagingVersion>
<MicrosoftDotNetRemoteExecutorVersion>5.0.0-beta.20453.7</MicrosoftDotNetRemoteExecutorVersion>
<MicrosoftDotNetVersionToolsTasksVersion>5.0.0-beta.20453.7</MicrosoftDotNetVersionToolsTasksVersion>
<MicrosoftDotNetApiCompatVersion>5.0.0-beta.20459.8</MicrosoftDotNetApiCompatVersion>
<MicrosoftDotNetBuildTasksFeedVersion>5.0.0-beta.20459.8</MicrosoftDotNetBuildTasksFeedVersion>
<MicrosoftDotNetCodeAnalysisVersion>5.0.0-beta.20459.8</MicrosoftDotNetCodeAnalysisVersion>
<MicrosoftDotNetGenAPIVersion>5.0.0-beta.20459.8</MicrosoftDotNetGenAPIVersion>
<MicrosoftDotNetGenFacadesVersion>5.0.0-beta.20459.8</MicrosoftDotNetGenFacadesVersion>
<MicrosoftDotNetXUnitExtensionsVersion>5.0.0-beta.20459.8</MicrosoftDotNetXUnitExtensionsVersion>
<MicrosoftDotNetXUnitConsoleRunnerVersion>2.5.1-beta.20459.8</MicrosoftDotNetXUnitConsoleRunnerVersion>
<MicrosoftDotNetBuildTasksPackagingVersion>5.0.0-beta.20459.8</MicrosoftDotNetBuildTasksPackagingVersion>
<MicrosoftDotNetRemoteExecutorVersion>5.0.0-beta.20459.8</MicrosoftDotNetRemoteExecutorVersion>
<MicrosoftDotNetVersionToolsTasksVersion>5.0.0-beta.20459.8</MicrosoftDotNetVersionToolsTasksVersion>
<!-- Installer dependencies -->
<MicrosoftNETCoreAppVersion>5.0.0-preview.4.20202.18</MicrosoftNETCoreAppVersion>
<MicrosoftNETCoreDotNetHostVersion>5.0.0-preview.4.20202.18</MicrosoftNETCoreDotNetHostVersion>

Просмотреть файл

@ -12,10 +12,10 @@
"python3": "3.7.1"
},
"msbuild-sdks": {
"Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "5.0.0-beta.20453.7",
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20453.7",
"Microsoft.DotNet.Build.Tasks.SharedFramework.Sdk": "5.0.0-beta.20453.7",
"Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20453.7",
"Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "5.0.0-beta.20459.8",
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20459.8",
"Microsoft.DotNet.Build.Tasks.SharedFramework.Sdk": "5.0.0-beta.20459.8",
"Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20459.8",
"Microsoft.FIX-85B6-MERGE-9C38-CONFLICT": "1.0.0",
"Microsoft.NET.Sdk.IL": "5.0.0-preview.8.20359.4",
"Microsoft.Build.NoTargets": "1.0.53",

Просмотреть файл

@ -248,11 +248,8 @@
<HelixPreCommand Include="export __TestEnv=$HELIX_WORKITEM_PAYLOAD/$(TestEnvFileName)" />
<HelixPreCommand Include="export __TestTimeout=$(TimeoutPerTestInMilliseconds)" Condition=" '$(TimeoutPerTestInMilliseconds)' != '' " />
<HelixPreCommand Include="export __CollectDumps=1" />
<HelixPreCommand Include="export __CrashDumpFolder=$HELIX_DUMP_FOLDER" Condition=" '$(TargetOS)' != 'OSX' " />
<HelixPreCommand Include="export __CrashDumpFolder=/cores" Condition=" '$(TargetOS)' == 'OSX' " /> <!-- Helix doesn't specify the dump folder for OSX 10.14, so we need to manually specify it. Tracked by dotnet/core-eng#7872 -->
<HelixPreCommand Include="export __CrashDumpFolder=$HELIX_DUMP_FOLDER" />
<HelixPreCommand Include="cat $__TestEnv" />
<HelixPreCommand Include="sudo bash -c 'echo $HELIX_DUMP_FOLDER/core.%u.%p > /proc/sys/kernel/core_pattern'" Condition=" '$(TargetOS)' != 'OSX' " />
<HelixPreCommand Include="ulimit -c unlimited" Condition=" '$(TargetOS)' == 'OSX' " />
</ItemGroup>
<PropertyGroup>

Просмотреть файл

@ -278,8 +278,8 @@ internal static partial class Interop
public UNICODE_STRING* strCngAlgId; // CNG algorithm identifier.
public int cChainingModes; // Set to 0 if CNG algorithm does not have a chaining mode.
public UNICODE_STRING* rgstrChainingModes; // Set to NULL if CNG algorithm does not have a chaining mode.
public int dwMinBitLength; // Blacklist key sizes less than this. Set to 0 if not defined or CNG algorithm implies bit length.
public int dwMaxBitLength; // Blacklist key sizes greater than this. Set to 0 if not defined or CNG algorithm implies bit length.
public int dwMinBitLength; // Minimum bit length for the specified CNG algorithm. Set to 0 if not defined or CNG algorithm implies bit length.
public int dwMaxBitLength; // Maximum bit length for the specified CNG algorithm. Set to 0 if not defined or CNG algorithm implies bit length.
public enum TlsAlgorithmUsage
{

Просмотреть файл

@ -360,7 +360,15 @@ namespace System.Net.Http
protected internal override System.Net.Http.HttpResponseMessage Send(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { throw null; }
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 Func<SocketsHttpConnectionContext, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask<System.IO.Stream>>? ConnectCallback { get { throw null; } set { } }
}
public sealed class SocketsHttpConnectionContext
{
internal SocketsHttpConnectionContext() { }
public DnsEndPoint DnsEndPoint { get { throw null; } }
public HttpRequestMessage RequestMessage { get { throw null; } }
}
public enum HttpKeepAlivePingPolicy
{
WithActiveRequests,

Просмотреть файл

@ -585,4 +585,7 @@
<data name="net_http_requested_version_server_refused" xml:space="preserve">
<value>Requesting HTTP version {0} with version policy {1} while server offers only version fallback.</value>
</data>
<data name="net_http_sync_operations_not_allowed_with_connect_callback" xml:space="preserve">
<value>Synchronous operation is not supported when a ConnectCallback is specified on the SocketsHttpHandler instance.</value>
</data>
</root>

Просмотреть файл

@ -173,7 +173,7 @@
<Compile Include="System\Net\Http\SocketsHttpHandler\MultiProxy.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\RawConnectionStream.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\RedirectHandler.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\SocketsConnectionFactory.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\SocketsHttpConnectionContext.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\SocketsHttpHandler.cs" />
<Compile Include="System\Net\Http\SocketsHttpHandler\SystemProxyInfo.cs" />
<Compile Include="$(CommonPath)System\Net\NTAuthentication.Common.cs"
@ -671,6 +671,7 @@
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\SocketsHttpHandler\SocketsHttpConnectionContext.cs" />
<Compile Include="System\Net\Http\BrowserHttpHandler\SystemProxyInfo.Browser.cs" />
<Compile Include="System\Net\Http\BrowserHttpHandler\SocketsHttpHandler.cs" />
<Compile Include="System\Net\Http\BrowserHttpHandler\BrowserHttpHandler.cs" />

Просмотреть файл

@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.IO;
using System.Net.Security;
using System.Threading;
using System.Threading.Tasks;
@ -170,5 +171,11 @@ namespace System.Net.Http
get => throw new PlatformNotSupportedException();
set => throw new PlatformNotSupportedException();
}
public Func<SocketsHttpConnectionContext, CancellationToken, ValueTask<Stream>>? ConnectCallback
{
get => throw new PlatformNotSupportedException();
set => throw new PlatformNotSupportedException();
}
}
}

Просмотреть файл

@ -31,11 +31,11 @@ namespace System.Net.Http
}
}
public static async ValueTask<Stream> ConnectAsync(SocketsConnectionFactory factory, DnsEndPoint endPoint, CancellationToken cancellationToken)
public static async ValueTask<Stream> ConnectAsync(Func<SocketsHttpConnectionContext, CancellationToken, ValueTask<Stream>> callback, DnsEndPoint endPoint, HttpRequestMessage requestMessage, CancellationToken cancellationToken)
{
try
{
return await factory.ConnectAsync(endPoint, cancellationToken).ConfigureAwait(false);
return await callback(new SocketsHttpConnectionContext(endPoint, requestMessage), cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException ex) when (ex.CancellationToken == cancellationToken)
{

Просмотреть файл

@ -1286,20 +1286,42 @@ namespace System.Net.Http
}
}
private static readonly SocketsConnectionFactory s_defaultConnectionFactory = new SocketsConnectionFactory(SocketType.Stream, ProtocolType.Tcp);
private static async ValueTask<Stream> DefaultConnectAsync(SocketsHttpConnectionContext context, CancellationToken cancellationToken)
{
Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
socket.NoDelay = true;
try
{
await socket.ConnectAsync(context.DnsEndPoint, cancellationToken).ConfigureAwait(false);
return new NetworkStream(socket, ownsSocket: true);
}
catch
{
socket.Dispose();
throw;
}
}
private static readonly Func<SocketsHttpConnectionContext, CancellationToken, ValueTask<Stream>> s_defaultConnectCallback = DefaultConnectAsync;
private ValueTask<Stream> ConnectToTcpHostAsync(string host, int port, HttpRequestMessage initialRequest, bool async, CancellationToken cancellationToken)
{
if (async)
{
SocketsConnectionFactory connectionFactory = s_defaultConnectionFactory;
Func<SocketsHttpConnectionContext, CancellationToken, ValueTask<Stream>> connectCallback = Settings._connectCallback ?? s_defaultConnectCallback;
var endPoint = new DnsEndPoint(host, port);
return ConnectHelper.ConnectAsync(connectionFactory, endPoint, cancellationToken);
return ConnectHelper.ConnectAsync(connectCallback, endPoint, initialRequest, cancellationToken);
}
// Synchronous path.
if (Settings._connectCallback is not null)
{
throw new NotSupportedException(SR.net_http_sync_operations_not_allowed_with_connect_callback);
}
try
{
return new ValueTask<Stream>(ConnectHelper.Connect(host, port, cancellationToken));

Просмотреть файл

@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Net.Security;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@ -55,6 +56,8 @@ namespace System.Net.Http
internal bool _enableMultipleHttp2Connections;
internal Func<SocketsHttpConnectionContext, CancellationToken, ValueTask<Stream>>? _connectCallback;
internal IDictionary<string, object?>? _properties;
public HttpConnectionSettings()
@ -108,6 +111,7 @@ namespace System.Net.Http
_requestHeaderEncodingSelector = _requestHeaderEncodingSelector,
_responseHeaderEncodingSelector = _responseHeaderEncodingSelector,
_enableMultipleHttp2Connections = _enableMultipleHttp2Connections,
_connectCallback = _connectCallback,
};
}

Просмотреть файл

@ -1,106 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
namespace System.Net.Http
{
/// <summary>
/// A factory to establish socket-based connections.
/// </summary>
/// <remarks>
/// When constructed with <see cref="ProtocolType.Tcp"/>, this factory will create connections with <see cref="Socket.NoDelay"/> enabled.
/// In case of IPv6 sockets <see cref="Socket.DualMode"/> is also enabled.
/// </remarks>
internal sealed class SocketsConnectionFactory
{
private readonly AddressFamily _addressFamily;
private readonly SocketType _socketType;
private readonly ProtocolType _protocolType;
/// <summary>
/// Initializes a new instance of the <see cref="SocketsConnectionFactory"/> class.
/// </summary>
/// <param name="addressFamily">The <see cref="AddressFamily"/> to forward to the socket.</param>
/// <param name="socketType">The <see cref="SocketType"/> to forward to the socket.</param>
/// <param name="protocolType">The <see cref="ProtocolType"/> to forward to the socket.</param>
public SocketsConnectionFactory(
AddressFamily addressFamily,
SocketType socketType,
ProtocolType protocolType)
{
_addressFamily = addressFamily;
_socketType = socketType;
_protocolType = protocolType;
}
/// <summary>
/// Initializes a new instance of the <see cref="SocketsConnectionFactory"/> class
/// that will forward <see cref="AddressFamily.InterNetworkV6"/> to the Socket constructor.
/// </summary>
/// <param name="socketType">The <see cref="SocketType"/> to forward to the socket.</param>
/// <param name="protocolType">The <see cref="ProtocolType"/> to forward to the socket.</param>
/// <remarks>The created socket will be an IPv6 socket with <see cref="Socket.DualMode"/> enabled.</remarks>
public SocketsConnectionFactory(SocketType socketType, ProtocolType protocolType)
: this(AddressFamily.InterNetworkV6, socketType, protocolType)
{
}
public async ValueTask<Stream> ConnectAsync(
EndPoint? endPoint,
CancellationToken cancellationToken = default)
{
if (endPoint == null) throw new ArgumentNullException(nameof(endPoint));
cancellationToken.ThrowIfCancellationRequested();
Socket socket = CreateSocket(_addressFamily, _socketType, _protocolType, endPoint);
try
{
await socket.ConnectAsync(endPoint, cancellationToken).ConfigureAwait(false);
return new NetworkStream(socket, true);
}
catch
{
socket.Dispose();
throw;
}
}
/// <summary>
/// Creates the socket that shall be used with the connection.
/// </summary>
/// <param name="addressFamily">The <see cref="AddressFamily"/> to forward to the socket.</param>
/// <param name="socketType">The <see cref="SocketType"/> to forward to the socket.</param>
/// <param name="protocolType">The <see cref="ProtocolType"/> to forward to the socket.</param>
/// <param name="endPoint">The <see cref="EndPoint"/> this socket will be connected to.</param>
/// <returns>A new unconnected <see cref="Socket"/>.</returns>
/// <remarks>
/// In case of TCP sockets, the default implementation of this method will create a socket with <see cref="Socket.NoDelay"/> enabled.
/// In case of IPv6 sockets <see cref="Socket.DualMode"/> is also be enabled.
/// </remarks>
private Socket CreateSocket(
AddressFamily addressFamily,
SocketType socketType,
ProtocolType protocolType,
EndPoint? endPoint)
{
Socket socket = new Socket(addressFamily, socketType, protocolType);
if (protocolType == ProtocolType.Tcp)
{
socket.NoDelay = true;
}
if (addressFamily == AddressFamily.InterNetworkV6)
{
socket.DualMode = true;
}
return socket;
}
}
}

Просмотреть файл

@ -0,0 +1,30 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace System.Net.Http
{
/// <summary>
/// Represents the context passed to the ConnectCallback for a SocketsHttpHandler instance.
/// </summary>
public sealed class SocketsHttpConnectionContext
{
private readonly DnsEndPoint _dnsEndPoint;
private readonly HttpRequestMessage _requestMessage;
internal SocketsHttpConnectionContext(DnsEndPoint dnsEndPoint, HttpRequestMessage requestMessage)
{
_dnsEndPoint = dnsEndPoint;
_requestMessage = requestMessage;
}
/// <summary>
/// The DnsEndPoint to be used by the ConnectCallback to establish the connection.
/// </summary>
public DnsEndPoint DnsEndPoint => _dnsEndPoint;
/// <summary>
/// The initial HttpRequestMessage that is causing the connection to be created.
/// </summary>
public HttpRequestMessage RequestMessage => _requestMessage;
}
}

Просмотреть файл

@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net.Security;
using System.Threading;
using System.Threading.Tasks;
@ -362,6 +363,19 @@ namespace System.Net.Http
internal bool SupportsProxy => true;
internal bool SupportsRedirectConfiguration => true;
/// <summary>
/// When non-null, a custom callback used to open new connections.
/// </summary>
public Func<SocketsHttpConnectionContext, CancellationToken, ValueTask<Stream>>? ConnectCallback
{
get => _settings._connectCallback;
set
{
CheckDisposedOrStarted();
_settings._connectCallback = value;
}
}
public IDictionary<string, object?> Properties =>
_settings._properties ?? (_settings._properties = new Dictionary<string, object?>());

Просмотреть файл

@ -10,6 +10,7 @@ using System.Net.Security;
using System.Net.Sockets;
using System.Net.Test.Common;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
@ -1835,6 +1836,23 @@ namespace System.Net.Http.Functional.Tests
}
}
[Fact]
public void ConnectCallback_GetSet_Roundtrips()
{
using (var handler = new SocketsHttpHandler())
{
Assert.Null(handler.ConnectCallback);
Func<SocketsHttpConnectionContext, CancellationToken, ValueTask<Stream>> f = (context, token) => default;
handler.ConnectCallback = f;
Assert.Equal(f, handler.ConnectCallback);
handler.ConnectCallback = null;
Assert.Null(handler.ConnectCallback);
}
}
[Theory]
[InlineData(false)]
[InlineData(true)]
@ -1872,6 +1890,7 @@ namespace System.Net.Http.Functional.Tests
Assert.NotNull(handler.SslOptions);
Assert.True(handler.UseCookies);
Assert.True(handler.UseProxy);
Assert.Null(handler.ConnectCallback);
Assert.Throws(expectedExceptionType, () => handler.AllowAutoRedirect = false);
Assert.Throws(expectedExceptionType, () => handler.AutomaticDecompression = DecompressionMethods.GZip);
@ -1891,6 +1910,7 @@ namespace System.Net.Http.Functional.Tests
Assert.Throws(expectedExceptionType, () => handler.KeepAlivePingTimeout = TimeSpan.FromSeconds(5));
Assert.Throws(expectedExceptionType, () => handler.KeepAlivePingDelay = TimeSpan.FromSeconds(5));
Assert.Throws(expectedExceptionType, () => handler.KeepAlivePingPolicy = HttpKeepAlivePingPolicy.WithActiveRequests);
Assert.Throws(expectedExceptionType, () => handler.ConnectCallback = (context, token) => default);
}
}
}
@ -2251,6 +2271,235 @@ namespace System.Net.Http.Functional.Tests
}
}
public abstract class SocketsHttpHandlerTest_ConnectCallback : HttpClientHandlerTestBase
{
public SocketsHttpHandlerTest_ConnectCallback(ITestOutputHelper output) : base(output) { }
[Fact]
public void ConnectCallback_SyncRequest_Fails()
{
using SocketsHttpHandler handler = new SocketsHttpHandler
{
ConnectCallback = (context, token) => default,
};
using HttpClient client = CreateHttpClient(handler);
Assert.ThrowsAny<NotSupportedException>(() => client.Send(new HttpRequestMessage(HttpMethod.Get, $"http://bing.com")));
}
[Fact]
public async void ConnectCallback_ContextHasCorrectProperties_Success()
{
await LoopbackServerFactory.CreateClientAndServerAsync(
async uri =>
{
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
using HttpClientHandler handler = CreateHttpClientHandler();
handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
var socketsHandler = (SocketsHttpHandler)GetUnderlyingSocketsHttpHandler(handler);
socketsHandler.ConnectCallback = async (context, token) =>
{
Assert.Equal(uri.Host, context.DnsEndPoint.Host);
Assert.Equal(uri.Port, context.DnsEndPoint.Port);
Assert.Equal(requestMessage, context.RequestMessage);
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
await s.ConnectAsync(context.DnsEndPoint, token);
return new NetworkStream(s, ownsSocket: true);
};
using HttpClient client = CreateHttpClient(handler);
HttpResponseMessage response = await client.SendAsync(requestMessage);
Assert.Equal("foo", await response.Content.ReadAsStringAsync());
},
async server =>
{
await server.AcceptConnectionSendResponseAndCloseAsync(content: "foo");
});
}
[Fact]
public async Task ConnectCallback_BindLocalAddress_Success()
{
await LoopbackServerFactory.CreateClientAndServerAsync(
async uri =>
{
using HttpClientHandler handler = CreateHttpClientHandler();
handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
var socketsHandler = (SocketsHttpHandler)GetUnderlyingSocketsHttpHandler(handler);
socketsHandler.ConnectCallback = async (context, token) =>
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.Bind(new IPEndPoint(IPAddress.Loopback, 0));
await s.ConnectAsync(context.DnsEndPoint, token);
s.NoDelay = true;
return new NetworkStream(s, ownsSocket: true);
};
using HttpClient client = CreateHttpClient(handler);
string response = await client.GetStringAsync(uri);
Assert.Equal("foo", response);
},
async server =>
{
await server.AcceptConnectionSendResponseAndCloseAsync(content: "foo");
});
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task ConnectCallback_UseVirtualNetwork_Success(bool useSsl)
{
var vn = new VirtualNetwork();
using var clientStream = new VirtualNetworkStream(vn, isServer: false, gracefulShutdown: true);
using var serverStream = new VirtualNetworkStream(vn, isServer: true, gracefulShutdown: true);
GenericLoopbackOptions options = new GenericLoopbackOptions() { UseSsl = useSsl };
Task serverTask = Task.Run(async () =>
{
using GenericLoopbackConnection loopbackConnection = await LoopbackServerFactory.CreateConnectionAsync(socket: null, serverStream, options);
await loopbackConnection.InitializeConnectionAsync();
HttpRequestData requestData = await loopbackConnection.ReadRequestDataAsync();
await loopbackConnection.SendResponseAsync(content: "foo");
Assert.Equal("/foo", requestData.Path);
});
Task clientTask = Task.Run(async () =>
{
using HttpClientHandler handler = CreateHttpClientHandler();
handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
var socketsHandler = (SocketsHttpHandler)GetUnderlyingSocketsHttpHandler(handler);
socketsHandler.ConnectCallback = (context, token) => new ValueTask<Stream>(clientStream);
using HttpClient client = CreateHttpClient(handler);
string response = await client.GetStringAsync($"{(options.UseSsl ? "https" : "http")}://nowhere.invalid/foo");
Assert.Equal("foo", response);
});
await new[] { serverTask, clientTask }.WhenAllOrAnyFailed(60_000);
}
[ConditionalTheory(nameof(PlatformSupportsUnixDomainSockets))]
[InlineData(true)]
[InlineData(false)]
public async Task ConnectCallback_UseUnixDomainSocket_Success(bool useSsl)
{
GenericLoopbackOptions options = new GenericLoopbackOptions() { UseSsl = useSsl };
string guid = $"{Guid.NewGuid():N}";
UnixDomainSocketEndPoint serverEP = new UnixDomainSocketEndPoint(Path.Combine(Path.GetTempPath(), guid));
Socket listenSocket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
listenSocket.Bind(serverEP);
listenSocket.Listen();
using HttpClientHandler handler = CreateHttpClientHandler();
handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
var socketsHandler = (SocketsHttpHandler)GetUnderlyingSocketsHttpHandler(handler);
socketsHandler.ConnectCallback = async (context, token) =>
{
string hostname = context.DnsEndPoint.Host;
UnixDomainSocketEndPoint clientEP = new UnixDomainSocketEndPoint(Path.Combine(Path.GetTempPath(), hostname));
Socket clientSocket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
await clientSocket.ConnectAsync(clientEP);
return new NetworkStream(clientSocket, ownsSocket: true);
};
using HttpClient client = CreateHttpClient(handler);
Task<string> clientTask = client.GetStringAsync($"{(options.UseSsl ? "https" : "http")}://{guid}/foo");
Socket serverSocket = await listenSocket.AcceptAsync();
using GenericLoopbackConnection loopbackConnection = await LoopbackServerFactory.CreateConnectionAsync(socket: null, new NetworkStream(serverSocket, ownsSocket: true), options);
await loopbackConnection.InitializeConnectionAsync();
HttpRequestData requestData = await loopbackConnection.ReadRequestDataAsync();
Assert.Equal("/foo", requestData.Path);
await loopbackConnection.SendResponseAsync(content: "foo");
string response = await clientTask;
Assert.Equal("foo", response);
}
[Fact]
public async Task ConnectCallback_ConnectionPrefix_Success()
{
byte[] RequestPrefix = Encoding.UTF8.GetBytes("request prefix\r\n");
byte[] ResponsePrefix = Encoding.UTF8.GetBytes("response prefix\r\n");
Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
listenSocket.Listen();
using HttpClientHandler handler = CreateHttpClientHandler();
var socketsHandler = (SocketsHttpHandler)GetUnderlyingSocketsHttpHandler(handler);
socketsHandler.ConnectCallback = async (context, token) =>
{
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
await clientSocket.ConnectAsync(listenSocket.LocalEndPoint);
Stream clientStream = new NetworkStream(clientSocket, ownsSocket: true);
await clientStream.WriteAsync(RequestPrefix);
byte[] buffer = new byte[ResponsePrefix.Length];
await clientStream.ReadAsync(buffer);
Assert.True(buffer.SequenceEqual(ResponsePrefix));
return clientStream;
};
using HttpClient client = CreateHttpClient(handler);
Task<string> clientTask = client.GetStringAsync($"http://nowhere.invalid/foo");
Socket serverSocket = await listenSocket.AcceptAsync();
Stream serverStream = new NetworkStream(serverSocket, ownsSocket: true);
byte[] buffer = new byte[RequestPrefix.Length];
await serverStream.ReadAsync(buffer);
Assert.True(buffer.SequenceEqual(RequestPrefix));
await serverStream.WriteAsync(ResponsePrefix);
using GenericLoopbackConnection loopbackConnection = await LoopbackServerFactory.CreateConnectionAsync(socket: null, serverStream);
await loopbackConnection.InitializeConnectionAsync();
HttpRequestData requestData = await loopbackConnection.ReadRequestDataAsync();
Assert.Equal("/foo", requestData.Path);
await loopbackConnection.SendResponseAsync(content: "foo");
string response = await clientTask;
Assert.Equal("foo", response);
}
private static bool PlatformSupportsUnixDomainSockets => Socket.OSSupportsUnixDomainSockets;
}
public sealed class SocketsHttpHandlerTest_ConnectCallback_Http11 : SocketsHttpHandlerTest_ConnectCallback
{
public SocketsHttpHandlerTest_ConnectCallback_Http11(ITestOutputHelper output) : base(output) { }
}
[ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.SupportsAlpn))]
public sealed class SocketsHttpHandlerTest_ConnectCallback_Http2 : SocketsHttpHandlerTest_ConnectCallback
{
public SocketsHttpHandlerTest_ConnectCallback_Http2(ITestOutputHelper output) : base(output) { }
}
[ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.SupportsAlpn))]
public sealed class SocketsHttpHandlerTest_Cookies_Http2 : HttpClientHandlerTest_Cookies
{

Просмотреть файл

@ -79,7 +79,11 @@ namespace System.Text.Unicode
long tempUtf8CodeUnitCountAdjustment = 0;
int tempScalarCountAdjustment = 0;
if ((AdvSimd.Arm64.IsSupported && BitConverter.IsLittleEndian) || Sse2.IsSupported)
// Per https://github.com/dotnet/runtime/issues/41699, temporarily disabling
// ARM64-intrinsicified code paths. ARM64 platforms may still use the vectorized
// non-intrinsicified 'else' block below.
if (/* (AdvSimd.Arm64.IsSupported && BitConverter.IsLittleEndian) || */ Sse2.IsSupported)
{
if (inputLength >= Vector128<ushort>.Count)
{