Pool HttpSys request buffers (#17314)
This commit is contained in:
parent
6f2b107b88
commit
ca23b1a325
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
|
|
@ -11,20 +11,45 @@ namespace TestClient
|
|||
public class Program
|
||||
{
|
||||
private const string Address =
|
||||
// "http://localhost:5000/public/1kb.txt";
|
||||
"https://localhost:9090/public/1kb.txt";
|
||||
"http://localhost:5000/public/1kb.txt";
|
||||
// "https://localhost:9090/public/1kb.txt";
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
WebRequestHandler handler = new WebRequestHandler();
|
||||
handler.ServerCertificateValidationCallback = (_, __, ___, ____) => true;
|
||||
Console.WriteLine("Ready");
|
||||
Console.ReadKey();
|
||||
|
||||
var handler = new HttpClientHandler();
|
||||
handler.MaxConnectionsPerServer = 500;
|
||||
handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
|
||||
// handler.UseDefaultCredentials = true;
|
||||
handler.Credentials = new NetworkCredential(@"redmond\chrross", "passwird");
|
||||
HttpClient client = new HttpClient(handler);
|
||||
|
||||
/*
|
||||
RunParallelRequests(client);
|
||||
|
||||
// RunManualRequests(client);
|
||||
|
||||
// RunWebSocketClient().Wait();
|
||||
|
||||
Console.WriteLine("Done");
|
||||
// Console.ReadKey();
|
||||
}
|
||||
|
||||
private static void RunManualRequests(HttpClient client)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Console.WriteLine("Press any key to send request");
|
||||
Console.ReadKey();
|
||||
var result = client.GetAsync(Address).Result;
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RunParallelRequests(HttpClient client)
|
||||
{
|
||||
int completionCount = 0;
|
||||
int iterations = 30000;
|
||||
int iterations = 100000;
|
||||
for (int i = 0; i < iterations; i++)
|
||||
{
|
||||
client.GetAsync(Address)
|
||||
|
|
@ -34,19 +59,7 @@ namespace TestClient
|
|||
while (completionCount < iterations)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
}*/
|
||||
|
||||
while (true)
|
||||
{
|
||||
Console.WriteLine("Press any key to send request");
|
||||
Console.ReadKey();
|
||||
var result = client.GetAsync(Address).Result;
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
// RunWebSocketClient().Wait();
|
||||
// Console.WriteLine("Done");
|
||||
// Console.ReadKey();
|
||||
}
|
||||
|
||||
public static async Task RunWebSocketClient()
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All Rights Reserved
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
|
||||
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
|
||||
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
|
||||
// NON-INFRINGEMENT.
|
||||
// See the Apache 2 License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("TestClient")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("TestClient")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2012")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("8db62eb3-48c0-4049-b33e-271c738140a0")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("0.5")]
|
||||
[assembly: AssemblyVersion("0.5")]
|
||||
[assembly: AssemblyFileVersion("0.5.40117.0")]
|
||||
|
|
@ -1,64 +1,13 @@
|
|||
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{8B828433-B333-4C19-96AE-00BFFF9D8841}</ProjectGuid>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>TestClient</RootNamespace>
|
||||
<AssemblyName>TestClient</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<StartupObject>TestClient.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Net.Http.WebRequest" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.Extensions.Logging.Console" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="Pack" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
|
@ -18,8 +17,6 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
private TaskCompletionSource<RequestContext> _tcs;
|
||||
private HttpSysListener _server;
|
||||
private NativeRequestContext _nativeRequestContext;
|
||||
private const int DefaultBufferSize = 4096;
|
||||
private const int AlignmentPadding = 8;
|
||||
|
||||
internal AsyncAcceptContext(HttpSysListener server)
|
||||
{
|
||||
|
|
@ -192,32 +189,14 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
{
|
||||
_nativeRequestContext?.ReleasePins();
|
||||
_nativeRequestContext?.Dispose();
|
||||
//Debug.Assert(size != 0, "unexpected size");
|
||||
|
||||
// We can't reuse overlapped objects
|
||||
uint newSize = size.HasValue ? size.Value : DefaultBufferSize;
|
||||
var backingBuffer = new byte[newSize + AlignmentPadding];
|
||||
|
||||
var boundHandle = Server.RequestQueue.BoundHandle;
|
||||
var nativeOverlapped = new SafeNativeOverlapped(boundHandle,
|
||||
boundHandle.AllocateNativeOverlapped(IOCallback, this, backingBuffer));
|
||||
boundHandle.AllocateNativeOverlapped(IOCallback, this, pinData: null));
|
||||
|
||||
var requestAddress = Marshal.UnsafeAddrOfPinnedArrayElement(backingBuffer, 0);
|
||||
|
||||
// TODO:
|
||||
// Apparently the HttpReceiveHttpRequest memory alignment requirements for non - ARM processors
|
||||
// are different than for ARM processors. We have seen 4 - byte - aligned buffers allocated on
|
||||
// virtual x64/x86 machines which were accepted by HttpReceiveHttpRequest without errors. In
|
||||
// these cases the buffer alignment may cause reading values at invalid offset. Setting buffer
|
||||
// alignment to 0 for now.
|
||||
//
|
||||
// _bufferAlignment = (int)(requestAddress.ToInt64() & 0x07);
|
||||
|
||||
var bufferAlignment = 0;
|
||||
|
||||
var nativeRequest = (HttpApiTypes.HTTP_REQUEST*)(requestAddress + bufferAlignment);
|
||||
// nativeRequest
|
||||
_nativeRequestContext = new NativeRequestContext(nativeOverlapped, bufferAlignment, nativeRequest, backingBuffer, requestId);
|
||||
_nativeRequestContext = new NativeRequestContext(nativeOverlapped, Server.MemoryPool, size, requestId);
|
||||
}
|
||||
|
||||
public object AsyncState
|
||||
|
|
|
|||
|
|
@ -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.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
|
@ -32,6 +33,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
|||
// 0.5 seconds per request. Respond with a 400 Bad Request.
|
||||
private const int UnknownHeaderLimit = 1000;
|
||||
|
||||
internal MemoryPool<byte> MemoryPool { get; } = SlabMemoryPoolFactory.Create();
|
||||
|
||||
private volatile State _state; // m_State is set only within lock blocks, but often read outside locks.
|
||||
|
||||
private ServerSession _serverSession;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core HTTP server that uses the Windows HTTP Server API.</Description>
|
||||
|
|
@ -13,6 +13,10 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Compile Include="$(SharedSourceRoot)HttpSys\**\*.cs" />
|
||||
<Compile Include="$(SharedSourceRoot)Buffers.MemoryPool\*.cs" LinkBase="MemoryPool" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// 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.Text;
|
||||
|
||||
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||
|
|
@ -14,16 +15,7 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
|
||||
internal static unsafe string GetString(byte* pBytes, int byteCount)
|
||||
{
|
||||
// net451: return new string(pBytes, 0, byteCount, Encoding);
|
||||
|
||||
var charCount = Encoding.GetCharCount(pBytes, byteCount);
|
||||
var chars = new char[charCount];
|
||||
fixed (char* pChars = chars)
|
||||
{
|
||||
var count = Encoding.GetChars(pBytes, byteCount, pChars, charCount);
|
||||
System.Diagnostics.Debug.Assert(count == charCount);
|
||||
}
|
||||
return new string(chars);
|
||||
return Encoding.GetString(new ReadOnlySpan<byte>(pBytes, byteCount));
|
||||
}
|
||||
|
||||
internal static byte[] GetBytes(string myString)
|
||||
|
|
|
|||
|
|
@ -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.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Collections.ObjectModel;
|
||||
|
|
@ -17,24 +18,45 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
internal unsafe class NativeRequestContext : IDisposable
|
||||
{
|
||||
private const int AlignmentPadding = 8;
|
||||
private const int DefaultBufferSize = 4096 - AlignmentPadding;
|
||||
private IntPtr _originalBufferAddress;
|
||||
private HttpApiTypes.HTTP_REQUEST* _nativeRequest;
|
||||
private byte[] _backingBuffer;
|
||||
private IMemoryOwner<byte> _backingBuffer;
|
||||
private MemoryHandle _memoryHandle;
|
||||
private int _bufferAlignment;
|
||||
private SafeNativeOverlapped _nativeOverlapped;
|
||||
private bool _permanentlyPinned;
|
||||
private bool _disposed;
|
||||
|
||||
// To be used by HttpSys
|
||||
internal NativeRequestContext(SafeNativeOverlapped nativeOverlapped,
|
||||
int bufferAlignment,
|
||||
HttpApiTypes.HTTP_REQUEST* nativeRequest,
|
||||
byte[] backingBuffer,
|
||||
ulong requestId)
|
||||
internal NativeRequestContext(SafeNativeOverlapped nativeOverlapped, MemoryPool<Byte> memoryPool, uint? bufferSize, ulong requestId)
|
||||
{
|
||||
_nativeOverlapped = nativeOverlapped;
|
||||
_bufferAlignment = bufferAlignment;
|
||||
_nativeRequest = nativeRequest;
|
||||
_backingBuffer = backingBuffer;
|
||||
|
||||
// TODO:
|
||||
// Apparently the HttpReceiveHttpRequest memory alignment requirements for non - ARM processors
|
||||
// are different than for ARM processors. We have seen 4 - byte - aligned buffers allocated on
|
||||
// virtual x64/x86 machines which were accepted by HttpReceiveHttpRequest without errors. In
|
||||
// these cases the buffer alignment may cause reading values at invalid offset. Setting buffer
|
||||
// alignment to 0 for now.
|
||||
//
|
||||
// _bufferAlignment = (int)(requestAddress.ToInt64() & 0x07);
|
||||
_bufferAlignment = 0;
|
||||
|
||||
var newSize = (int)(bufferSize ?? DefaultBufferSize) + AlignmentPadding;
|
||||
if (newSize <= memoryPool.MaxBufferSize)
|
||||
{
|
||||
_backingBuffer = memoryPool.Rent(newSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No size limit
|
||||
_backingBuffer = MemoryPool<byte>.Shared.Rent(newSize);
|
||||
}
|
||||
_backingBuffer.Memory.Span.Fill(0);// Zero the buffer
|
||||
_memoryHandle = _backingBuffer.Memory.Pin();
|
||||
_nativeRequest = (HttpApiTypes.HTTP_REQUEST*)((long)_memoryHandle.Pointer + _bufferAlignment);
|
||||
|
||||
RequestId = requestId;
|
||||
}
|
||||
|
||||
|
|
@ -94,15 +116,17 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
|
||||
internal uint Size
|
||||
{
|
||||
get { return (uint)_backingBuffer.Length - AlignmentPadding; }
|
||||
get { return (uint)_backingBuffer.Memory.Length - AlignmentPadding; }
|
||||
}
|
||||
|
||||
// ReleasePins() should be called exactly once. It must be called before Dispose() is called, which means it must be called
|
||||
// before an object (Request) which closes the RequestContext on demand is returned to the application.
|
||||
internal void ReleasePins()
|
||||
{
|
||||
Debug.Assert(_nativeRequest != null || _backingBuffer == null, "RequestContextBase::ReleasePins()|ReleasePins() called twice.");
|
||||
Debug.Assert(_nativeRequest != null, "RequestContextBase::ReleasePins()|ReleasePins() called twice.");
|
||||
_originalBufferAddress = (IntPtr)_nativeRequest;
|
||||
_memoryHandle.Dispose();
|
||||
_memoryHandle = default;
|
||||
_nativeRequest = null;
|
||||
_nativeOverlapped?.Dispose();
|
||||
_nativeOverlapped = null;
|
||||
|
|
@ -110,8 +134,14 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
Debug.Assert(_nativeRequest == null, "RequestContextBase::Dispose()|Dispose() called before ReleasePins().");
|
||||
_nativeOverlapped?.Dispose();
|
||||
if (!_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
Debug.Assert(_nativeRequest == null, "RequestContextBase::Dispose()|Dispose() called before ReleasePins().");
|
||||
_nativeOverlapped?.Dispose();
|
||||
_memoryHandle.Dispose();
|
||||
_backingBuffer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// These methods require the HTTP_REQUEST to still be pinned in its original location.
|
||||
|
|
@ -272,7 +302,7 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
}
|
||||
else
|
||||
{
|
||||
fixed (byte* pMemoryBlob = _backingBuffer)
|
||||
fixed (byte* pMemoryBlob = _backingBuffer.Memory.Span)
|
||||
{
|
||||
var request = (HttpApiTypes.HTTP_REQUEST*)(pMemoryBlob + _bufferAlignment);
|
||||
long fixup = pMemoryBlob - (byte*)_originalBufferAddress;
|
||||
|
|
@ -306,7 +336,7 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
else
|
||||
{
|
||||
// Return value.
|
||||
fixed (byte* pMemoryBlob = _backingBuffer)
|
||||
fixed (byte* pMemoryBlob = _backingBuffer.Memory.Span)
|
||||
{
|
||||
var request = (HttpApiTypes.HTTP_REQUEST*)(pMemoryBlob + _bufferAlignment);
|
||||
long fixup = pMemoryBlob - (byte*)_originalBufferAddress;
|
||||
|
|
@ -366,7 +396,7 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
}
|
||||
else
|
||||
{
|
||||
fixed (byte* pMemoryBlob = _backingBuffer)
|
||||
fixed (byte* pMemoryBlob = _backingBuffer.Memory.Span)
|
||||
{
|
||||
var request = (HttpApiTypes.HTTP_REQUEST*)(pMemoryBlob + _bufferAlignment);
|
||||
return GetEndPointHelper(localEndpoint, request, pMemoryBlob);
|
||||
|
|
@ -426,7 +456,7 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
}
|
||||
else
|
||||
{
|
||||
fixed (byte* pMemoryBlob = _backingBuffer)
|
||||
fixed (byte* pMemoryBlob = _backingBuffer.Memory.Span)
|
||||
{
|
||||
var request = (HttpApiTypes.HTTP_REQUEST*)(pMemoryBlob + _bufferAlignment);
|
||||
long fixup = pMemoryBlob - (byte*)_originalBufferAddress;
|
||||
|
|
@ -490,7 +520,7 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
}
|
||||
else
|
||||
{
|
||||
fixed (byte* pMemoryBlob = _backingBuffer)
|
||||
fixed (byte* pMemoryBlob = _backingBuffer.Memory.Span)
|
||||
{
|
||||
var request = (HttpApiTypes.HTTP_REQUEST_V2*)(pMemoryBlob + _bufferAlignment);
|
||||
return GetRequestInfo(_originalBufferAddress, request);
|
||||
|
|
@ -514,7 +544,7 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
var offset = (long)requestInfo.pInfo - (long)baseAddress;
|
||||
info.Add(
|
||||
(int)requestInfo.InfoType,
|
||||
new ReadOnlyMemory<byte>(_backingBuffer, (int)offset, (int)requestInfo.InfoLength));
|
||||
_backingBuffer.Memory.Slice((int)offset, (int)requestInfo.InfoLength));
|
||||
}
|
||||
|
||||
return new ReadOnlyDictionary<int, ReadOnlyMemory<byte>>(info);
|
||||
|
|
@ -528,7 +558,7 @@ namespace Microsoft.AspNetCore.HttpSys.Internal
|
|||
}
|
||||
else
|
||||
{
|
||||
fixed (byte* pMemoryBlob = _backingBuffer)
|
||||
fixed (byte* pMemoryBlob = _backingBuffer.Memory.Span)
|
||||
{
|
||||
var request = (HttpApiTypes.HTTP_REQUEST_V2*)(pMemoryBlob + _bufferAlignment);
|
||||
return GetClientCertificate(_originalBufferAddress, request);
|
||||
|
|
|
|||
Loading…
Reference in New Issue