Merge remote-tracking branch 'origin/release/3.1' into merge/release/3.1-to-master

This commit is contained in:
Javier Calvarro Nelson 2019-09-21 04:52:15 -07:00
commit 2587f74c31
10 changed files with 144 additions and 4 deletions

View File

@ -451,6 +451,10 @@ stages:
testResultsFiles: '*.xml'
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Flaky'
artifacts:
- name: Windows_Test_Dumps
path: artifacts/dumps/
publishOnError: true
includeForks: false
- name: Windows_Test_Logs
path: artifacts/log/
publishOnError: true
@ -475,6 +479,10 @@ stages:
- script: ./src/ProjectTemplates/build.cmd -ci -test -NoRestore -NoBuild -NoBuilddeps "/p:RunTemplateTests=true /bl:artifacts/log/template.test.binlog"
displayName: Test Templates
artifacts:
- name: Windows_Test_Templates_Dumps
path: artifacts/dumps/
publishOnError: true
includeForks: false
- name: Windows_Test_Templates_Logs
path: artifacts/log/
publishOnError: true

View File

@ -129,7 +129,7 @@ jobs:
- ${{ if and(eq(parameters.agentOs, 'Windows'), eq(parameters.isTestingJob, true)) }}:
- powershell: ./eng/scripts/InstallProcDump.ps1
displayName: Install ProcDump
- powershell: ./eng/scripts/StartDumpCollectionForHangingBuilds.ps1 $(ProcDumpPath)procdump.exe artifacts/log/ (Get-Date).AddMinutes(160) dotnet
- powershell: ./eng/scripts/StartDumpCollectionForHangingBuilds.ps1 $(ProcDumpPath)procdump.exe artifacts/dumps/ (Get-Date).AddMinutes(160) dotnet
displayName: Start background dump collection
- ${{ if eq(parameters.installNodeJs, 'true') }}:
- task: NodeTool@0
@ -171,7 +171,7 @@ jobs:
- ${{ parameters.afterBuild }}
- ${{ if and(eq(parameters.agentOs, 'Windows'), eq(parameters.isTestingJob, true)) }}:
- powershell: ./eng/scripts/FinishDumpCollectionForHangingBuilds.ps1 artifacts/log/
- powershell: ./eng/scripts/FinishDumpCollectionForHangingBuilds.ps1 artifacts/dumps/
displayName: Finish background dump collection
continueOnError: true
condition: always()

View File

@ -57,6 +57,10 @@ namespace Microsoft.AspNetCore.Server.HttpSys
public Microsoft.AspNetCore.Server.HttpSys.TimeoutManager Timeouts { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
public Microsoft.AspNetCore.Server.HttpSys.UrlPrefixCollection UrlPrefixes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
}
public partial interface IHttpSysRequestInfoFeature
{
System.Collections.Generic.IReadOnlyDictionary<int, System.ReadOnlyMemory<byte>> RequestInfo { get; }
}
public sealed partial class TimeoutManager
{
internal TimeoutManager() { }

View File

@ -34,7 +34,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
IHttpUpgradeFeature,
IHttpRequestIdentifierFeature,
IHttpMaxRequestBodySizeFeature,
IHttpBodyControlFeature
IHttpBodyControlFeature,
IHttpSysRequestInfoFeature
{
private RequestContext _requestContext;
private IFeatureCollection _features;
@ -546,6 +547,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
int ITlsHandshakeFeature.KeyExchangeStrength => Request.KeyExchangeStrength;
IReadOnlyDictionary<int, ReadOnlyMemory<byte>> IHttpSysRequestInfoFeature.RequestInfo => Request.RequestInfo;
internal async Task OnResponseStart()
{
if (_responseStarted)

View File

@ -0,0 +1,25 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
// Note: This will also be useful for IIS in-proc.
// Plan: Have Microsoft.AspNetCore.Server.IIS take a dependency on Microsoft.AspNetCore.Server.HttpSys and implement this interface.
namespace Microsoft.AspNetCore.Server.HttpSys
{
/// <summary>
/// This exposes the Http.Sys HTTP_REQUEST_INFO extensibility point as opaque data for the caller to interperate.
/// https://docs.microsoft.com/en-us/windows/win32/api/http/ns-http-http_request_v2
/// https://docs.microsoft.com/en-us/windows/win32/api/http/ns-http-http_request_info
/// </summary>
public interface IHttpSysRequestInfoFeature
{
/// <summary>
/// A collection of the HTTP_REQUEST_INFO for the current request. The integer represents the identifying
/// HTTP_REQUEST_INFO_TYPE enum value. The Memory is opaque bytes that need to be interperted in the format
/// specified by the enum value.
/// </summary>
public IReadOnlyDictionary<int, ReadOnlyMemory<byte>> RequestInfo { get; }
}
}

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
@ -31,6 +32,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
private AspNetCore.HttpSys.Internal.SocketAddress _localEndPoint;
private AspNetCore.HttpSys.Internal.SocketAddress _remoteEndPoint;
private IReadOnlyDictionary<int, ReadOnlyMemory<byte>> _requestInfo;
private bool _isDisposed = false;
internal Request(RequestContext requestContext, NativeRequestContext nativeRequestContext)
@ -252,6 +255,18 @@ namespace Microsoft.AspNetCore.Server.HttpSys
public int KeyExchangeStrength { get; private set; }
public IReadOnlyDictionary<int, ReadOnlyMemory<byte>> RequestInfo
{
get
{
if (_requestInfo == null)
{
_requestInfo = _nativeRequestContext.GetRequestInfo();
}
return _requestInfo;
}
}
private void GetTlsHandshakeResults()
{
var handshake = _nativeRequestContext.GetTlsHandshake();

View File

@ -26,6 +26,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
{ typeof(RequestContext), ctx => ctx.RequestContext },
{ typeof(IHttpMaxRequestBodySizeFeature), _identityFunc },
{ typeof(IHttpBodyControlFeature), _identityFunc },
{ typeof(IHttpSysRequestInfoFeature), _identityFunc },
};
private readonly FeatureContext _featureContext;

View File

@ -3,7 +3,9 @@
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
@ -12,6 +14,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Connections.Features;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.HttpSys.Internal;
using Microsoft.AspNetCore.Testing;
using Xunit;
@ -160,6 +163,46 @@ namespace Microsoft.AspNetCore.Server.HttpSys
}
}
[ConditionalFact]
[OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, WindowsVersions.Win2008R2)]
public async Task Https_ITlsHandshakeFeature_MatchesIHttpSysExtensionInfoFeature()
{
using (Utilities.CreateDynamicHttpsServer(out var address, async httpContext =>
{
try
{
var tlsFeature = httpContext.Features.Get<ITlsHandshakeFeature>();
var requestInfoFeature = httpContext.Features.Get<IHttpSysRequestInfoFeature>();
Assert.NotNull(tlsFeature);
Assert.NotNull(requestInfoFeature);
Assert.True(requestInfoFeature.RequestInfo.Count > 0);
var tlsInfo = requestInfoFeature.RequestInfo[(int)HttpApiTypes.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeSslProtocol];
HttpApiTypes.HTTP_SSL_PROTOCOL_INFO tlsCopy;
unsafe
{
using var handle = tlsInfo.Pin();
tlsCopy = Marshal.PtrToStructure<HttpApiTypes.HTTP_SSL_PROTOCOL_INFO>((IntPtr)handle.Pointer);
}
// Assert.Equal(tlsFeature.Protocol, tlsCopy.Protocol); // These don't directly match because the native and managed enums use different values.
Assert.Equal(tlsFeature.CipherAlgorithm, tlsCopy.CipherType);
Assert.Equal(tlsFeature.CipherStrength, (int)tlsCopy.CipherStrength);
Assert.Equal(tlsFeature.HashAlgorithm, tlsCopy.HashType);
Assert.Equal(tlsFeature.HashStrength, (int)tlsCopy.HashStrength);
Assert.Equal(tlsFeature.KeyExchangeAlgorithm, tlsCopy.KeyExchangeType);
Assert.Equal(tlsFeature.KeyExchangeStrength, (int)tlsCopy.KeyExchangeStrength);
}
catch (Exception ex)
{
await httpContext.Response.WriteAsync(ex.ToString());
}
}))
{
string response = await SendRequestAsync(address);
Assert.Equal(string.Empty, response);
}
}
private async Task<string> SendRequestAsync(string uri,
X509Certificate cert = null)
{

View File

@ -1,8 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<TestGroupName>HttpSys.FunctionalTests</TestGroupName>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>

View File

@ -3,6 +3,8 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Net.Sockets;
using System.Runtime.InteropServices;
@ -478,5 +480,43 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
}
return dataRead;
}
internal IReadOnlyDictionary<int, ReadOnlyMemory<byte>> GetRequestInfo()
{
if (_permanentlyPinned)
{
return GetRequestInfo((IntPtr)_nativeRequest, (HttpApiTypes.HTTP_REQUEST_V2*)_nativeRequest);
}
else
{
fixed (byte* pMemoryBlob = _backingBuffer)
{
var request = (HttpApiTypes.HTTP_REQUEST_V2*)(pMemoryBlob + _bufferAlignment);
return GetRequestInfo(_originalBufferAddress, request);
}
}
}
private IReadOnlyDictionary<int, ReadOnlyMemory<byte>> GetRequestInfo(IntPtr baseAddress, HttpApiTypes.HTTP_REQUEST_V2* nativeRequest)
{
var count = nativeRequest->RequestInfoCount;
if (count == 0)
{
return ImmutableDictionary<int, ReadOnlyMemory<byte>>.Empty;
}
var info = new Dictionary<int, ReadOnlyMemory<byte>>(count);
for (var i = 0; i < count; i++)
{
var requestInfo = nativeRequest->pRequestInfo[i];
var offset = (long)requestInfo.pInfo - (long)baseAddress;
info.Add(
(int)requestInfo.InfoType,
new ReadOnlyMemory<byte>(_backingBuffer, (int)offset, (int)requestInfo.InfoLength));
}
return new ReadOnlyDictionary<int, ReadOnlyMemory<byte>>(info);
}
}
}