Create shared package folder for IIS Integration In-process. (#397)
This commit is contained in:
parent
58f82c5b32
commit
231cbffe1a
|
|
@ -45,6 +45,41 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{85914BA9
|
||||||
build\Key.snk = build\Key.snk
|
build\Key.snk = build\Key.snk
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{AB6964C9-A7AF-4FAC-BEA1-C8A538EC989E}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Microsoft.AspNetCore.HttpSys.Sources", "Microsoft.AspNetCore.HttpSys.Sources", "{4AB1E069-2A8A-4D46-98AE-CC82E3497038}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\Constants.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\Constants.cs
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NativeInterop", "NativeInterop", "{94AD33C9-1BDD-4385-A850-4B24FD5D5012}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\CookedUrl.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\CookedUrl.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\HeapAllocHandle.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\HeapAllocHandle.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\HttpApiTypes.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\HttpApiTypes.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\HttpSysRequestHeader.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\HttpSysRequestHeader.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\HttpSysResponseHeader.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\HttpSysResponseHeader.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\NativeRequestInput.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\NativeRequestInput.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\NclUtilities.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\NclUtilities.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\SafeLocalFreeChannelBinding.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\SafeLocalFreeChannelBinding.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\SafeLocalMemHandle.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\SafeLocalMemHandle.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\SafeNativeOverlapped.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\SafeNativeOverlapped.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\SocketAddress.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\SocketAddress.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\UnsafeNativeMethods.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\NativeInterop\UnsafeNativeMethods.cs
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RequestProcessing", "RequestProcessing", "{AA8C91BD-D558-468B-9258-1E186884F78D}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\HeaderCollection.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\HeaderCollection.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\HeaderEncoding.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\HeaderEncoding.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\HeaderParser.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\HeaderParser.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\HttpKnownHeaderNames.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\HttpKnownHeaderNames.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\NativeRequestContext.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\NativeRequestContext.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\RequestHeaders.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\RequestHeaders.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\RequestHeaders.Generated.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\RequestHeaders.Generated.cs
|
||||||
|
shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\SslStatus.cs = shared\Microsoft.AspNetCore.HttpSys.Sources\RequestProcessing\SslStatus.cs
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -131,6 +166,9 @@ Global
|
||||||
{8BFA392A-8B67-4454-916B-67C545EDFAEF} = {3A1E31E3-2794-4CA3-B8E2-253E96BDE514}
|
{8BFA392A-8B67-4454-916B-67C545EDFAEF} = {3A1E31E3-2794-4CA3-B8E2-253E96BDE514}
|
||||||
{E837249E-E666-4DF2-AFC3-7A4D70234F9F} = {E183C826-1360-4DFF-9994-F33CED5C8525}
|
{E837249E-E666-4DF2-AFC3-7A4D70234F9F} = {E183C826-1360-4DFF-9994-F33CED5C8525}
|
||||||
{85914BA9-4168-48C5-9C3F-E2E8B1479A6E} = {5E9B546C-17AC-4BDF-BCB3-5955D4755ED8}
|
{85914BA9-4168-48C5-9C3F-E2E8B1479A6E} = {5E9B546C-17AC-4BDF-BCB3-5955D4755ED8}
|
||||||
|
{4AB1E069-2A8A-4D46-98AE-CC82E3497038} = {AB6964C9-A7AF-4FAC-BEA1-C8A538EC989E}
|
||||||
|
{94AD33C9-1BDD-4385-A850-4B24FD5D5012} = {4AB1E069-2A8A-4D46-98AE-CC82E3497038}
|
||||||
|
{AA8C91BD-D558-468B-9258-1E186884F78D} = {4AB1E069-2A8A-4D46-98AE-CC82E3497038}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {34B42B42-FA09-41AB-9216-14073990C504}
|
SolutionGuid = {34B42B42-FA09-41AB-9216-14073990C504}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
{
|
{
|
||||||
|
"adx-nonshipping": {
|
||||||
|
"rules": [],
|
||||||
|
"packages": {
|
||||||
|
"Microsoft.AspNetCore.HttpSys.Sources": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Default": {
|
"Default": {
|
||||||
"rules": [
|
"rules": [
|
||||||
"DefaultCompositeRule"
|
"DefaultCompositeRule"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal static class Constants
|
internal static class Constants
|
||||||
{
|
{
|
||||||
|
|
@ -4,14 +4,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
// Note this type should only be used while the request buffer remains pinned
|
// Note this type should only be used while the request buffer remains pinned
|
||||||
internal class CookedUrl
|
internal class CookedUrl
|
||||||
{
|
{
|
||||||
private readonly HttpApi.HTTP_COOKED_URL _nativeCookedUrl;
|
private readonly HttpApiTypes.HTTP_COOKED_URL _nativeCookedUrl;
|
||||||
|
|
||||||
internal CookedUrl(HttpApi.HTTP_COOKED_URL nativeCookedUrl)
|
internal CookedUrl(HttpApiTypes.HTTP_COOKED_URL nativeCookedUrl)
|
||||||
{
|
{
|
||||||
_nativeCookedUrl = nativeCookedUrl;
|
_nativeCookedUrl = nativeCookedUrl;
|
||||||
}
|
}
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.Win32.SafeHandles;
|
using Microsoft.Win32.SafeHandles;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal sealed class HeapAllocHandle : SafeHandleZeroOrMinusOneIsInvalid
|
internal sealed class HeapAllocHandle : SafeHandleZeroOrMinusOneIsInvalid
|
||||||
{
|
{
|
||||||
|
|
@ -0,0 +1,694 @@
|
||||||
|
// 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;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
|
{
|
||||||
|
internal static unsafe class HttpApiTypes
|
||||||
|
{
|
||||||
|
internal enum HTTP_API_VERSION
|
||||||
|
{
|
||||||
|
Invalid,
|
||||||
|
Version10,
|
||||||
|
Version20,
|
||||||
|
}
|
||||||
|
|
||||||
|
// see http.w for definitions
|
||||||
|
internal enum HTTP_SERVER_PROPERTY
|
||||||
|
{
|
||||||
|
HttpServerAuthenticationProperty,
|
||||||
|
HttpServerLoggingProperty,
|
||||||
|
HttpServerQosProperty,
|
||||||
|
HttpServerTimeoutsProperty,
|
||||||
|
HttpServerQueueLengthProperty,
|
||||||
|
HttpServerStateProperty,
|
||||||
|
HttpServer503VerbosityProperty,
|
||||||
|
HttpServerBindingProperty,
|
||||||
|
HttpServerExtendedAuthenticationProperty,
|
||||||
|
HttpServerListenEndpointProperty,
|
||||||
|
HttpServerChannelBindProperty,
|
||||||
|
HttpServerProtectionLevelProperty,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently only one request info type is supported but the enum is for future extensibility.
|
||||||
|
|
||||||
|
internal enum HTTP_REQUEST_INFO_TYPE
|
||||||
|
{
|
||||||
|
HttpRequestInfoTypeAuth,
|
||||||
|
HttpRequestInfoTypeChannelBind,
|
||||||
|
HttpRequestInfoTypeSslProtocol,
|
||||||
|
HttpRequestInfoTypeSslTokenBinding
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum HTTP_RESPONSE_INFO_TYPE
|
||||||
|
{
|
||||||
|
HttpResponseInfoTypeMultipleKnownHeaders,
|
||||||
|
HttpResponseInfoTypeAuthenticationProperty,
|
||||||
|
HttpResponseInfoTypeQosProperty,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum HTTP_TIMEOUT_TYPE
|
||||||
|
{
|
||||||
|
EntityBody,
|
||||||
|
DrainEntityBody,
|
||||||
|
RequestQueue,
|
||||||
|
IdleConnection,
|
||||||
|
HeaderWait,
|
||||||
|
MinSendRate,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal const int MaxTimeout = 6;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_VERSION
|
||||||
|
{
|
||||||
|
internal ushort MajorVersion;
|
||||||
|
internal ushort MinorVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_KNOWN_HEADER
|
||||||
|
{
|
||||||
|
internal ushort RawValueLength;
|
||||||
|
internal byte* pRawValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
internal struct HTTP_DATA_CHUNK
|
||||||
|
{
|
||||||
|
[FieldOffset(0)]
|
||||||
|
internal HTTP_DATA_CHUNK_TYPE DataChunkType;
|
||||||
|
|
||||||
|
[FieldOffset(8)]
|
||||||
|
internal FromMemory fromMemory;
|
||||||
|
|
||||||
|
[FieldOffset(8)]
|
||||||
|
internal FromFileHandle fromFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct FromMemory
|
||||||
|
{
|
||||||
|
// 4 bytes for 32bit, 8 bytes for 64bit
|
||||||
|
internal IntPtr pBuffer;
|
||||||
|
internal uint BufferLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct FromFileHandle
|
||||||
|
{
|
||||||
|
internal ulong offset;
|
||||||
|
internal ulong count;
|
||||||
|
internal IntPtr fileHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTPAPI_VERSION
|
||||||
|
{
|
||||||
|
internal ushort HttpApiMajorVersion;
|
||||||
|
internal ushort HttpApiMinorVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_COOKED_URL
|
||||||
|
{
|
||||||
|
internal ushort FullUrlLength;
|
||||||
|
internal ushort HostLength;
|
||||||
|
internal ushort AbsPathLength;
|
||||||
|
internal ushort QueryStringLength;
|
||||||
|
internal ushort* pFullUrl;
|
||||||
|
internal ushort* pHost;
|
||||||
|
internal ushort* pAbsPath;
|
||||||
|
internal ushort* pQueryString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only cache unauthorized GETs + HEADs.
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_CACHE_POLICY
|
||||||
|
{
|
||||||
|
internal HTTP_CACHE_POLICY_TYPE Policy;
|
||||||
|
internal uint SecondsToLive;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum HTTP_CACHE_POLICY_TYPE : int
|
||||||
|
{
|
||||||
|
HttpCachePolicyNocache = 0,
|
||||||
|
HttpCachePolicyUserInvalidates = 1,
|
||||||
|
HttpCachePolicyTimeToLive = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct SOCKADDR
|
||||||
|
{
|
||||||
|
internal ushort sa_family;
|
||||||
|
internal byte sa_data;
|
||||||
|
internal byte sa_data_02;
|
||||||
|
internal byte sa_data_03;
|
||||||
|
internal byte sa_data_04;
|
||||||
|
internal byte sa_data_05;
|
||||||
|
internal byte sa_data_06;
|
||||||
|
internal byte sa_data_07;
|
||||||
|
internal byte sa_data_08;
|
||||||
|
internal byte sa_data_09;
|
||||||
|
internal byte sa_data_10;
|
||||||
|
internal byte sa_data_11;
|
||||||
|
internal byte sa_data_12;
|
||||||
|
internal byte sa_data_13;
|
||||||
|
internal byte sa_data_14;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_TRANSPORT_ADDRESS
|
||||||
|
{
|
||||||
|
internal SOCKADDR* pRemoteAddress;
|
||||||
|
internal SOCKADDR* pLocalAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_SSL_CLIENT_CERT_INFO
|
||||||
|
{
|
||||||
|
internal uint CertFlags;
|
||||||
|
internal uint CertEncodedSize;
|
||||||
|
internal byte* pCertEncoded;
|
||||||
|
internal void* Token;
|
||||||
|
internal byte CertDeniedByMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum HTTP_SERVICE_BINDING_TYPE : uint
|
||||||
|
{
|
||||||
|
HttpServiceBindingTypeNone = 0,
|
||||||
|
HttpServiceBindingTypeW,
|
||||||
|
HttpServiceBindingTypeA
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_SERVICE_BINDING_BASE
|
||||||
|
{
|
||||||
|
internal HTTP_SERVICE_BINDING_TYPE Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_REQUEST_CHANNEL_BIND_STATUS
|
||||||
|
{
|
||||||
|
internal IntPtr ServiceName;
|
||||||
|
internal IntPtr ChannelToken;
|
||||||
|
internal uint ChannelTokenSize;
|
||||||
|
internal uint Flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_UNKNOWN_HEADER
|
||||||
|
{
|
||||||
|
internal ushort NameLength;
|
||||||
|
internal ushort RawValueLength;
|
||||||
|
internal byte* pName;
|
||||||
|
internal byte* pRawValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_SSL_INFO
|
||||||
|
{
|
||||||
|
internal ushort ServerCertKeySize;
|
||||||
|
internal ushort ConnectionKeySize;
|
||||||
|
internal uint ServerCertIssuerSize;
|
||||||
|
internal uint ServerCertSubjectSize;
|
||||||
|
internal byte* pServerCertIssuer;
|
||||||
|
internal byte* pServerCertSubject;
|
||||||
|
internal HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo;
|
||||||
|
internal uint SslClientCertNegotiated;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_RESPONSE_HEADERS
|
||||||
|
{
|
||||||
|
internal ushort UnknownHeaderCount;
|
||||||
|
internal HTTP_UNKNOWN_HEADER* pUnknownHeaders;
|
||||||
|
internal ushort TrailerCount;
|
||||||
|
internal HTTP_UNKNOWN_HEADER* pTrailers;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_02;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_03;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_04;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_05;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_06;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_07;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_08;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_09;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_10;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_11;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_12;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_13;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_14;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_15;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_16;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_17;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_18;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_19;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_20;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_21;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_22;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_23;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_24;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_25;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_26;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_27;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_28;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_29;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_30;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_REQUEST_HEADERS
|
||||||
|
{
|
||||||
|
internal ushort UnknownHeaderCount;
|
||||||
|
internal HTTP_UNKNOWN_HEADER* pUnknownHeaders;
|
||||||
|
internal ushort TrailerCount;
|
||||||
|
internal HTTP_UNKNOWN_HEADER* pTrailers;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_02;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_03;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_04;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_05;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_06;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_07;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_08;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_09;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_10;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_11;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_12;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_13;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_14;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_15;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_16;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_17;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_18;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_19;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_20;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_21;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_22;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_23;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_24;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_25;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_26;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_27;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_28;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_29;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_30;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_31;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_32;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_33;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_34;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_35;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_36;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_37;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_38;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_39;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_40;
|
||||||
|
internal HTTP_KNOWN_HEADER KnownHeaders_41;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum HTTP_VERB : int
|
||||||
|
{
|
||||||
|
HttpVerbUnparsed = 0,
|
||||||
|
HttpVerbUnknown = 1,
|
||||||
|
HttpVerbInvalid = 2,
|
||||||
|
HttpVerbOPTIONS = 3,
|
||||||
|
HttpVerbGET = 4,
|
||||||
|
HttpVerbHEAD = 5,
|
||||||
|
HttpVerbPOST = 6,
|
||||||
|
HttpVerbPUT = 7,
|
||||||
|
HttpVerbDELETE = 8,
|
||||||
|
HttpVerbTRACE = 9,
|
||||||
|
HttpVerbCONNECT = 10,
|
||||||
|
HttpVerbTRACK = 11,
|
||||||
|
HttpVerbMOVE = 12,
|
||||||
|
HttpVerbCOPY = 13,
|
||||||
|
HttpVerbPROPFIND = 14,
|
||||||
|
HttpVerbPROPPATCH = 15,
|
||||||
|
HttpVerbMKCOL = 16,
|
||||||
|
HttpVerbLOCK = 17,
|
||||||
|
HttpVerbUNLOCK = 18,
|
||||||
|
HttpVerbSEARCH = 19,
|
||||||
|
HttpVerbMaximum = 20,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static readonly string[] HttpVerbs = new string[]
|
||||||
|
{
|
||||||
|
null,
|
||||||
|
"Unknown",
|
||||||
|
"Invalid",
|
||||||
|
"OPTIONS",
|
||||||
|
"GET",
|
||||||
|
"HEAD",
|
||||||
|
"POST",
|
||||||
|
"PUT",
|
||||||
|
"DELETE",
|
||||||
|
"TRACE",
|
||||||
|
"CONNECT",
|
||||||
|
"TRACK",
|
||||||
|
"MOVE",
|
||||||
|
"COPY",
|
||||||
|
"PROPFIND",
|
||||||
|
"PROPPATCH",
|
||||||
|
"MKCOL",
|
||||||
|
"LOCK",
|
||||||
|
"UNLOCK",
|
||||||
|
"SEARCH",
|
||||||
|
};
|
||||||
|
|
||||||
|
internal enum HTTP_DATA_CHUNK_TYPE : int
|
||||||
|
{
|
||||||
|
HttpDataChunkFromMemory = 0,
|
||||||
|
HttpDataChunkFromFileHandle = 1,
|
||||||
|
HttpDataChunkFromFragmentCache = 2,
|
||||||
|
HttpDataChunkMaximum = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_RESPONSE_INFO
|
||||||
|
{
|
||||||
|
internal HTTP_RESPONSE_INFO_TYPE Type;
|
||||||
|
internal uint Length;
|
||||||
|
internal HTTP_MULTIPLE_KNOWN_HEADERS* pInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_RESPONSE
|
||||||
|
{
|
||||||
|
internal uint Flags;
|
||||||
|
internal HTTP_VERSION Version;
|
||||||
|
internal ushort StatusCode;
|
||||||
|
internal ushort ReasonLength;
|
||||||
|
internal byte* pReason;
|
||||||
|
internal HTTP_RESPONSE_HEADERS Headers;
|
||||||
|
internal ushort EntityChunkCount;
|
||||||
|
internal HTTP_DATA_CHUNK* pEntityChunks;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_RESPONSE_V2
|
||||||
|
{
|
||||||
|
internal HTTP_RESPONSE Response_V1;
|
||||||
|
internal ushort ResponseInfoCount;
|
||||||
|
internal HTTP_RESPONSE_INFO* pResponseInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum HTTP_RESPONSE_INFO_FLAGS : uint
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
PreserveOrder = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_MULTIPLE_KNOWN_HEADERS
|
||||||
|
{
|
||||||
|
internal HTTP_RESPONSE_HEADER_ID.Enum HeaderId;
|
||||||
|
internal HTTP_RESPONSE_INFO_FLAGS Flags;
|
||||||
|
internal ushort KnownHeaderCount;
|
||||||
|
internal HTTP_KNOWN_HEADER* KnownHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_REQUEST_AUTH_INFO
|
||||||
|
{
|
||||||
|
internal HTTP_AUTH_STATUS AuthStatus;
|
||||||
|
internal uint SecStatus;
|
||||||
|
internal uint Flags;
|
||||||
|
internal HTTP_REQUEST_AUTH_TYPE AuthType;
|
||||||
|
internal IntPtr AccessToken;
|
||||||
|
internal uint ContextAttributes;
|
||||||
|
internal uint PackedContextLength;
|
||||||
|
internal uint PackedContextType;
|
||||||
|
internal IntPtr PackedContext;
|
||||||
|
internal uint MutualAuthDataLength;
|
||||||
|
internal char* pMutualAuthData;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_REQUEST_INFO
|
||||||
|
{
|
||||||
|
internal HTTP_REQUEST_INFO_TYPE InfoType;
|
||||||
|
internal uint InfoLength;
|
||||||
|
internal HTTP_REQUEST_AUTH_INFO* pInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_REQUEST
|
||||||
|
{
|
||||||
|
internal uint Flags;
|
||||||
|
internal ulong ConnectionId;
|
||||||
|
internal ulong RequestId;
|
||||||
|
internal ulong UrlContext;
|
||||||
|
internal HTTP_VERSION Version;
|
||||||
|
internal HTTP_VERB Verb;
|
||||||
|
internal ushort UnknownVerbLength;
|
||||||
|
internal ushort RawUrlLength;
|
||||||
|
internal byte* pUnknownVerb;
|
||||||
|
internal byte* pRawUrl;
|
||||||
|
internal HTTP_COOKED_URL CookedUrl;
|
||||||
|
internal HTTP_TRANSPORT_ADDRESS Address;
|
||||||
|
internal HTTP_REQUEST_HEADERS Headers;
|
||||||
|
internal ulong BytesReceived;
|
||||||
|
internal ushort EntityChunkCount;
|
||||||
|
internal HTTP_DATA_CHUNK* pEntityChunks;
|
||||||
|
internal ulong RawConnectionId;
|
||||||
|
internal HTTP_SSL_INFO* pSslInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_REQUEST_V2
|
||||||
|
{
|
||||||
|
internal HTTP_REQUEST Request;
|
||||||
|
internal ushort RequestInfoCount;
|
||||||
|
internal HTTP_REQUEST_INFO* pRequestInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum HTTP_AUTH_STATUS
|
||||||
|
{
|
||||||
|
HttpAuthStatusSuccess,
|
||||||
|
HttpAuthStatusNotAuthenticated,
|
||||||
|
HttpAuthStatusFailure,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum HTTP_REQUEST_AUTH_TYPE
|
||||||
|
{
|
||||||
|
HttpRequestAuthTypeNone = 0,
|
||||||
|
HttpRequestAuthTypeBasic,
|
||||||
|
HttpRequestAuthTypeDigest,
|
||||||
|
HttpRequestAuthTypeNTLM,
|
||||||
|
HttpRequestAuthTypeNegotiate,
|
||||||
|
HttpRequestAuthTypeKerberos
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum HTTP_QOS_SETTING_TYPE
|
||||||
|
{
|
||||||
|
HttpQosSettingTypeBandwidth,
|
||||||
|
HttpQosSettingTypeConnectionLimit,
|
||||||
|
HttpQosSettingTypeFlowRate
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_SERVER_AUTHENTICATION_INFO
|
||||||
|
{
|
||||||
|
internal HTTP_FLAGS Flags;
|
||||||
|
internal HTTP_AUTH_TYPES AuthSchemes;
|
||||||
|
internal bool ReceiveMutualAuth;
|
||||||
|
internal bool ReceiveContextHandle;
|
||||||
|
internal bool DisableNTLMCredentialCaching;
|
||||||
|
internal ulong ExFlags;
|
||||||
|
HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS DigestParams;
|
||||||
|
HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS BasicParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS
|
||||||
|
{
|
||||||
|
internal ushort DomainNameLength;
|
||||||
|
internal char* DomainName;
|
||||||
|
internal ushort RealmLength;
|
||||||
|
internal char* Realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS
|
||||||
|
{
|
||||||
|
ushort RealmLength;
|
||||||
|
char* Realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_REQUEST_TOKEN_BINDING_INFO
|
||||||
|
{
|
||||||
|
public byte* TokenBinding;
|
||||||
|
public uint TokenBindingSize;
|
||||||
|
|
||||||
|
public byte* TlsUnique;
|
||||||
|
public uint TlsUniqueSize;
|
||||||
|
|
||||||
|
public char* KeyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_TIMEOUT_LIMIT_INFO
|
||||||
|
{
|
||||||
|
internal HTTP_FLAGS Flags;
|
||||||
|
internal ushort EntityBody;
|
||||||
|
internal ushort DrainEntityBody;
|
||||||
|
internal ushort RequestQueue;
|
||||||
|
internal ushort IdleConnection;
|
||||||
|
internal ushort HeaderWait;
|
||||||
|
internal uint MinSendRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_BINDING_INFO
|
||||||
|
{
|
||||||
|
internal HTTP_FLAGS Flags;
|
||||||
|
internal IntPtr RequestQueueHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_CONNECTION_LIMIT_INFO
|
||||||
|
{
|
||||||
|
internal HTTP_FLAGS Flags;
|
||||||
|
internal uint MaxConnections;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct HTTP_QOS_SETTING_INFO
|
||||||
|
{
|
||||||
|
internal HTTP_QOS_SETTING_TYPE QosType;
|
||||||
|
internal IntPtr QosSetting;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see http.w for definitions
|
||||||
|
[Flags]
|
||||||
|
internal enum HTTP_FLAGS : uint
|
||||||
|
{
|
||||||
|
NONE = 0x00000000,
|
||||||
|
HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY = 0x00000001,
|
||||||
|
HTTP_RECEIVE_SECURE_CHANNEL_TOKEN = 0x00000001,
|
||||||
|
HTTP_SEND_RESPONSE_FLAG_DISCONNECT = 0x00000001,
|
||||||
|
HTTP_SEND_RESPONSE_FLAG_MORE_DATA = 0x00000002,
|
||||||
|
HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA = 0x00000004,
|
||||||
|
HTTP_SEND_RESPONSE_FLAG_RAW_HEADER = 0x00000004,
|
||||||
|
HTTP_SEND_REQUEST_FLAG_MORE_DATA = 0x00000001,
|
||||||
|
HTTP_PROPERTY_FLAG_PRESENT = 0x00000001,
|
||||||
|
HTTP_INITIALIZE_SERVER = 0x00000001,
|
||||||
|
HTTP_INITIALIZE_CBT = 0x00000004,
|
||||||
|
HTTP_SEND_RESPONSE_FLAG_OPAQUE = 0x00000040,
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
internal enum HTTP_AUTH_TYPES : uint
|
||||||
|
{
|
||||||
|
NONE = 0x00000000,
|
||||||
|
HTTP_AUTH_ENABLE_BASIC = 0x00000001,
|
||||||
|
HTTP_AUTH_ENABLE_DIGEST = 0x00000002,
|
||||||
|
HTTP_AUTH_ENABLE_NTLM = 0x00000004,
|
||||||
|
HTTP_AUTH_ENABLE_NEGOTIATE = 0x00000008,
|
||||||
|
HTTP_AUTH_ENABLE_KERBEROS = 0x00000010,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class HTTP_RESPONSE_HEADER_ID
|
||||||
|
{
|
||||||
|
private static string[] _strings =
|
||||||
|
{
|
||||||
|
"Cache-Control",
|
||||||
|
"Connection",
|
||||||
|
"Date",
|
||||||
|
"Keep-Alive",
|
||||||
|
"Pragma",
|
||||||
|
"Trailer",
|
||||||
|
"Transfer-Encoding",
|
||||||
|
"Upgrade",
|
||||||
|
"Via",
|
||||||
|
"Warning",
|
||||||
|
|
||||||
|
"Allow",
|
||||||
|
"Content-Length",
|
||||||
|
"Content-Type",
|
||||||
|
"Content-Encoding",
|
||||||
|
"Content-Language",
|
||||||
|
"Content-Location",
|
||||||
|
"Content-MD5",
|
||||||
|
"Content-Range",
|
||||||
|
"Expires",
|
||||||
|
"Last-Modified",
|
||||||
|
|
||||||
|
"Accept-Ranges",
|
||||||
|
"Age",
|
||||||
|
"ETag",
|
||||||
|
"Location",
|
||||||
|
"Proxy-Authenticate",
|
||||||
|
"Retry-After",
|
||||||
|
"Server",
|
||||||
|
"Set-Cookie",
|
||||||
|
"Vary",
|
||||||
|
"WWW-Authenticate",
|
||||||
|
};
|
||||||
|
|
||||||
|
private static Dictionary<string, int> _lookupTable = CreateLookupTable();
|
||||||
|
|
||||||
|
private static Dictionary<string, int> CreateLookupTable()
|
||||||
|
{
|
||||||
|
Dictionary<string, int> lookupTable = new Dictionary<string, int>((int)Enum.HttpHeaderResponseMaximum, StringComparer.OrdinalIgnoreCase);
|
||||||
|
for (int i = 0; i < (int)Enum.HttpHeaderResponseMaximum; i++)
|
||||||
|
{
|
||||||
|
lookupTable.Add(_strings[i], i);
|
||||||
|
}
|
||||||
|
return lookupTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static int IndexOfKnownHeader(string HeaderName)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
return _lookupTable.TryGetValue(HeaderName, out index) ? index : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum Enum
|
||||||
|
{
|
||||||
|
HttpHeaderCacheControl = 0, // general-header [section 4.5]
|
||||||
|
HttpHeaderConnection = 1, // general-header [section 4.5]
|
||||||
|
HttpHeaderDate = 2, // general-header [section 4.5]
|
||||||
|
HttpHeaderKeepAlive = 3, // general-header [not in rfc]
|
||||||
|
HttpHeaderPragma = 4, // general-header [section 4.5]
|
||||||
|
HttpHeaderTrailer = 5, // general-header [section 4.5]
|
||||||
|
HttpHeaderTransferEncoding = 6, // general-header [section 4.5]
|
||||||
|
HttpHeaderUpgrade = 7, // general-header [section 4.5]
|
||||||
|
HttpHeaderVia = 8, // general-header [section 4.5]
|
||||||
|
HttpHeaderWarning = 9, // general-header [section 4.5]
|
||||||
|
|
||||||
|
HttpHeaderAllow = 10, // entity-header [section 7.1]
|
||||||
|
HttpHeaderContentLength = 11, // entity-header [section 7.1]
|
||||||
|
HttpHeaderContentType = 12, // entity-header [section 7.1]
|
||||||
|
HttpHeaderContentEncoding = 13, // entity-header [section 7.1]
|
||||||
|
HttpHeaderContentLanguage = 14, // entity-header [section 7.1]
|
||||||
|
HttpHeaderContentLocation = 15, // entity-header [section 7.1]
|
||||||
|
HttpHeaderContentMd5 = 16, // entity-header [section 7.1]
|
||||||
|
HttpHeaderContentRange = 17, // entity-header [section 7.1]
|
||||||
|
HttpHeaderExpires = 18, // entity-header [section 7.1]
|
||||||
|
HttpHeaderLastModified = 19, // entity-header [section 7.1]
|
||||||
|
|
||||||
|
// Response Headers
|
||||||
|
|
||||||
|
HttpHeaderAcceptRanges = 20, // response-header [section 6.2]
|
||||||
|
HttpHeaderAge = 21, // response-header [section 6.2]
|
||||||
|
HttpHeaderEtag = 22, // response-header [section 6.2]
|
||||||
|
HttpHeaderLocation = 23, // response-header [section 6.2]
|
||||||
|
HttpHeaderProxyAuthenticate = 24, // response-header [section 6.2]
|
||||||
|
HttpHeaderRetryAfter = 25, // response-header [section 6.2]
|
||||||
|
HttpHeaderServer = 26, // response-header [section 6.2]
|
||||||
|
HttpHeaderSetCookie = 27, // response-header [not in rfc]
|
||||||
|
HttpHeaderVary = 28, // response-header [section 6.2]
|
||||||
|
HttpHeaderWwwAuthenticate = 29, // response-header [section 6.2]
|
||||||
|
|
||||||
|
HttpHeaderResponseMaximum = 30,
|
||||||
|
|
||||||
|
HttpHeaderMaximum = 41
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal enum HttpSysRequestHeader
|
internal enum HttpSysRequestHeader
|
||||||
{
|
{
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal enum HttpSysResponseHeader
|
internal enum HttpSysResponseHeader
|
||||||
{
|
{
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal static class NclUtilities
|
internal static class NclUtilities
|
||||||
{
|
{
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Security.Authentication.ExtendedProtection;
|
using System.Security.Authentication.ExtendedProtection;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal class SafeLocalFreeChannelBinding : ChannelBinding
|
internal class SafeLocalFreeChannelBinding : ChannelBinding
|
||||||
{
|
{
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.Win32.SafeHandles;
|
using Microsoft.Win32.SafeHandles;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal sealed class SafeLocalMemHandle : SafeHandleZeroOrMinusOneIsInvalid
|
internal sealed class SafeLocalMemHandle : SafeHandleZeroOrMinusOneIsInvalid
|
||||||
{
|
{
|
||||||
|
|
@ -5,7 +5,7 @@ using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal class SafeNativeOverlapped : SafeHandle
|
internal class SafeNativeOverlapped : SafeHandle
|
||||||
{
|
{
|
||||||
|
|
@ -6,9 +6,10 @@ using System.Collections.Generic;
|
||||||
using System.Diagnostics.Contracts;
|
using System.Diagnostics.Contracts;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
// a little perf app measured these times when comparing the internal
|
// a little perf app measured these times when comparing the internal
|
||||||
// buffer implemented as a managed byte[] or unmanaged memory IntPtr
|
// buffer implemented as a managed byte[] or unmanaged memory IntPtr
|
||||||
|
|
@ -5,7 +5,7 @@ using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal static unsafe class UnsafeNclNativeMethods
|
internal static unsafe class UnsafeNclNativeMethods
|
||||||
{
|
{
|
||||||
|
|
@ -8,7 +8,7 @@ using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal class HeaderCollection : IHeaderDictionary
|
internal class HeaderCollection : IHeaderDictionary
|
||||||
{
|
{
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal static class HeaderEncoding
|
internal static class HeaderEncoding
|
||||||
{
|
{
|
||||||
|
|
@ -12,15 +12,15 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
// (e.g. IE and HttpWebRequest on intranets).
|
// (e.g. IE and HttpWebRequest on intranets).
|
||||||
private static Encoding Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false);
|
private static Encoding Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false);
|
||||||
|
|
||||||
internal static unsafe string GetString(sbyte* pBytes, int byteCount)
|
internal static unsafe string GetString(byte* pBytes, int byteCount)
|
||||||
{
|
{
|
||||||
// net451: return new string(pBytes, 0, byteCount, Encoding);
|
// net451: return new string(pBytes, 0, byteCount, Encoding);
|
||||||
|
|
||||||
var charCount = Encoding.GetCharCount((byte*)pBytes, byteCount);
|
var charCount = Encoding.GetCharCount(pBytes, byteCount);
|
||||||
var chars = new char[charCount];
|
var chars = new char[charCount];
|
||||||
fixed (char* pChars = chars)
|
fixed (char* pChars = chars)
|
||||||
{
|
{
|
||||||
var count = Encoding.GetChars((byte*)pBytes, byteCount, pChars, charCount);
|
var count = Encoding.GetChars(pBytes, byteCount, pChars, charCount);
|
||||||
System.Diagnostics.Debug.Assert(count == charCount);
|
System.Diagnostics.Debug.Assert(count == charCount);
|
||||||
}
|
}
|
||||||
return new string(chars);
|
return new string(chars);
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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.Collections.Generic;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal static class HeaderParser
|
internal static class HeaderParser
|
||||||
{
|
{
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal static class HttpKnownHeaderNames
|
internal static class HttpKnownHeaderNames
|
||||||
{
|
{
|
||||||
|
|
@ -0,0 +1,455 @@
|
||||||
|
// 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;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security.Principal;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
|
{
|
||||||
|
internal unsafe class NativeRequestContext : IDisposable
|
||||||
|
{
|
||||||
|
private const int AlignmentPadding = 8;
|
||||||
|
private IntPtr _originalBufferAddress;
|
||||||
|
private HttpApiTypes.HTTP_REQUEST* _nativeRequest;
|
||||||
|
private byte[] _backingBuffer;
|
||||||
|
private int _bufferAlignment;
|
||||||
|
private SafeNativeOverlapped _nativeOverlapped;
|
||||||
|
private bool _permanentlyPinned;
|
||||||
|
|
||||||
|
// To be used by HttpSys
|
||||||
|
internal NativeRequestContext(SafeNativeOverlapped nativeOverlapped,
|
||||||
|
int bufferAlignment,
|
||||||
|
HttpApiTypes.HTTP_REQUEST* nativeRequest,
|
||||||
|
byte[] backingBuffer,
|
||||||
|
ulong requestId)
|
||||||
|
{
|
||||||
|
_nativeOverlapped = nativeOverlapped;
|
||||||
|
_bufferAlignment = bufferAlignment;
|
||||||
|
_nativeRequest = nativeRequest;
|
||||||
|
_backingBuffer = backingBuffer;
|
||||||
|
RequestId = requestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// To be used by IIS Integration.
|
||||||
|
internal NativeRequestContext(HttpApiTypes.HTTP_REQUEST* request)
|
||||||
|
{
|
||||||
|
_nativeRequest = request;
|
||||||
|
_bufferAlignment = 0;
|
||||||
|
_permanentlyPinned = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal SafeNativeOverlapped NativeOverlapped => _nativeOverlapped;
|
||||||
|
|
||||||
|
internal HttpApiTypes.HTTP_REQUEST* NativeRequest
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Debug.Assert(_nativeRequest != null || _backingBuffer == null, "native request accessed after ReleasePins().");
|
||||||
|
return _nativeRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal HttpApiTypes.HTTP_REQUEST_V2* NativeRequestV2
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Debug.Assert(_nativeRequest != null || _backingBuffer == null, "native request accessed after ReleasePins().");
|
||||||
|
return (HttpApiTypes.HTTP_REQUEST_V2*)_nativeRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ulong RequestId
|
||||||
|
{
|
||||||
|
get { return NativeRequest->RequestId; }
|
||||||
|
set { NativeRequest->RequestId = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ulong ConnectionId => NativeRequest->ConnectionId;
|
||||||
|
|
||||||
|
internal HttpApiTypes.HTTP_VERB VerbId => NativeRequest->Verb;
|
||||||
|
|
||||||
|
internal ulong UrlContext => NativeRequest->UrlContext;
|
||||||
|
|
||||||
|
internal ushort UnknownHeaderCount => NativeRequest->Headers.UnknownHeaderCount;
|
||||||
|
|
||||||
|
internal SslStatus SslStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return NativeRequest->pSslInfo == null ? SslStatus.Insecure :
|
||||||
|
NativeRequest->pSslInfo->SslClientCertNegotiated == 0 ? SslStatus.NoClientCert :
|
||||||
|
SslStatus.ClientCert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal uint Size
|
||||||
|
{
|
||||||
|
get { return (uint)_backingBuffer.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.");
|
||||||
|
_originalBufferAddress = (IntPtr)_nativeRequest;
|
||||||
|
_nativeRequest = null;
|
||||||
|
_nativeOverlapped?.Dispose();
|
||||||
|
_nativeOverlapped = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Dispose()
|
||||||
|
{
|
||||||
|
Debug.Assert(_nativeRequest == null, "RequestContextBase::Dispose()|Dispose() called before ReleasePins().");
|
||||||
|
_nativeOverlapped?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// These methods require the HTTP_REQUEST to still be pinned in its original location.
|
||||||
|
|
||||||
|
internal string GetVerb()
|
||||||
|
{
|
||||||
|
var verb = NativeRequest->Verb;
|
||||||
|
if (verb > HttpApiTypes.HTTP_VERB.HttpVerbUnknown && verb < HttpApiTypes.HTTP_VERB.HttpVerbMaximum)
|
||||||
|
{
|
||||||
|
return HttpApiTypes.HttpVerbs[(int)verb];
|
||||||
|
}
|
||||||
|
else if (verb == HttpApiTypes.HTTP_VERB.HttpVerbUnknown && NativeRequest->pUnknownVerb != null)
|
||||||
|
{
|
||||||
|
return HeaderEncoding.GetString(NativeRequest->pUnknownVerb, NativeRequest->UnknownVerbLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal string GetRawUrl()
|
||||||
|
{
|
||||||
|
if (NativeRequest->pRawUrl != null && NativeRequest->RawUrlLength > 0)
|
||||||
|
{
|
||||||
|
return Marshal.PtrToStringAnsi((IntPtr)NativeRequest->pRawUrl, NativeRequest->RawUrlLength);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal byte[] GetRawUrlInBytes()
|
||||||
|
{
|
||||||
|
if (NativeRequest->pRawUrl != null && NativeRequest->RawUrlLength > 0)
|
||||||
|
{
|
||||||
|
var result = new byte[NativeRequest->RawUrlLength];
|
||||||
|
Marshal.Copy((IntPtr)NativeRequest->pRawUrl, result, 0, NativeRequest->RawUrlLength);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal CookedUrl GetCookedUrl()
|
||||||
|
{
|
||||||
|
return new CookedUrl(NativeRequest->CookedUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Version GetVersion()
|
||||||
|
{
|
||||||
|
var major = NativeRequest->Version.MajorVersion;
|
||||||
|
var minor = NativeRequest->Version.MinorVersion;
|
||||||
|
if (major == 1 && minor == 1)
|
||||||
|
{
|
||||||
|
return Constants.V1_1;
|
||||||
|
}
|
||||||
|
else if (major == 1 && minor == 0)
|
||||||
|
{
|
||||||
|
return Constants.V1_0;
|
||||||
|
}
|
||||||
|
return new Version(major, minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool CheckAuthenticated()
|
||||||
|
{
|
||||||
|
var requestInfo = NativeRequestV2->pRequestInfo;
|
||||||
|
var infoCount = NativeRequestV2->RequestInfoCount;
|
||||||
|
|
||||||
|
for (int i = 0; i < infoCount; i++)
|
||||||
|
{
|
||||||
|
var info = &requestInfo[i];
|
||||||
|
if (info != null
|
||||||
|
&& info->InfoType == HttpApiTypes.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeAuth
|
||||||
|
&& info->pInfo->AuthStatus == HttpApiTypes.HTTP_AUTH_STATUS.HttpAuthStatusSuccess)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal WindowsPrincipal GetUser()
|
||||||
|
{
|
||||||
|
var requestInfo = NativeRequestV2->pRequestInfo;
|
||||||
|
var infoCount = NativeRequestV2->RequestInfoCount;
|
||||||
|
|
||||||
|
for (int i = 0; i < infoCount; i++)
|
||||||
|
{
|
||||||
|
var info = &requestInfo[i];
|
||||||
|
if (info != null
|
||||||
|
&& info->InfoType == HttpApiTypes.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeAuth
|
||||||
|
&& info->pInfo->AuthStatus == HttpApiTypes.HTTP_AUTH_STATUS.HttpAuthStatusSuccess)
|
||||||
|
{
|
||||||
|
// Duplicates AccessToken
|
||||||
|
var identity = new WindowsIdentity(info->pInfo->AccessToken, GetAuthTypeFromRequest(info->pInfo->AuthType));
|
||||||
|
|
||||||
|
// Close the original
|
||||||
|
UnsafeNclNativeMethods.SafeNetHandles.CloseHandle(info->pInfo->AccessToken);
|
||||||
|
|
||||||
|
return new WindowsPrincipal(identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new WindowsPrincipal(WindowsIdentity.GetAnonymous()); // Anonymous / !IsAuthenticated
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetAuthTypeFromRequest(HttpApiTypes.HTTP_REQUEST_AUTH_TYPE input)
|
||||||
|
{
|
||||||
|
switch (input)
|
||||||
|
{
|
||||||
|
case HttpApiTypes.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeBasic:
|
||||||
|
return "Basic";
|
||||||
|
case HttpApiTypes.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeNTLM:
|
||||||
|
return "NTLM";
|
||||||
|
// case HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeDigest:
|
||||||
|
// return "Digest";
|
||||||
|
case HttpApiTypes.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeNegotiate:
|
||||||
|
return "Negotiate";
|
||||||
|
case HttpApiTypes.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeKerberos:
|
||||||
|
return "Kerberos";
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException(input.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// These methods are for accessing the request structure after it has been unpinned. They need to adjust addresses
|
||||||
|
// in case GC has moved the original object.
|
||||||
|
|
||||||
|
internal string GetKnownHeader(HttpSysRequestHeader header)
|
||||||
|
{
|
||||||
|
if (_permanentlyPinned)
|
||||||
|
{
|
||||||
|
return GetKnowHeaderHelper(header, 0, _nativeRequest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fixed (byte* pMemoryBlob = _backingBuffer)
|
||||||
|
{
|
||||||
|
var request = (HttpApiTypes.HTTP_REQUEST*)(pMemoryBlob + _bufferAlignment);
|
||||||
|
long fixup = pMemoryBlob - (byte*)_originalBufferAddress;
|
||||||
|
return GetKnowHeaderHelper(header, fixup, request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetKnowHeaderHelper(HttpSysRequestHeader header, long fixup, HttpApiTypes.HTTP_REQUEST* request)
|
||||||
|
{
|
||||||
|
int headerIndex = (int)header;
|
||||||
|
string value = null;
|
||||||
|
|
||||||
|
HttpApiTypes.HTTP_KNOWN_HEADER* pKnownHeader = (&request->Headers.KnownHeaders) + headerIndex;
|
||||||
|
// For known headers, when header value is empty, RawValueLength will be 0 and
|
||||||
|
// pRawValue will point to empty string ("\0")
|
||||||
|
if (pKnownHeader->pRawValue != null)
|
||||||
|
{
|
||||||
|
value = HeaderEncoding.GetString(pKnownHeader->pRawValue + fixup, pKnownHeader->RawValueLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void GetUnknownHeaders(IDictionary<string, StringValues> unknownHeaders)
|
||||||
|
{
|
||||||
|
if (_permanentlyPinned)
|
||||||
|
{
|
||||||
|
GetUnknownHeadersHelper(unknownHeaders, 0, _nativeRequest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Return value.
|
||||||
|
fixed (byte* pMemoryBlob = _backingBuffer)
|
||||||
|
{
|
||||||
|
var request = (HttpApiTypes.HTTP_REQUEST*)(pMemoryBlob + _bufferAlignment);
|
||||||
|
long fixup = pMemoryBlob - (byte*)_originalBufferAddress;
|
||||||
|
GetUnknownHeadersHelper(unknownHeaders, fixup, request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GetUnknownHeadersHelper(IDictionary<string, StringValues> unknownHeaders, long fixup, HttpApiTypes.HTTP_REQUEST* request)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
|
||||||
|
// unknown headers
|
||||||
|
if (request->Headers.UnknownHeaderCount != 0)
|
||||||
|
{
|
||||||
|
var pUnknownHeader = (HttpApiTypes.HTTP_UNKNOWN_HEADER*)(fixup + (byte*)request->Headers.pUnknownHeaders);
|
||||||
|
for (index = 0; index < request->Headers.UnknownHeaderCount; index++)
|
||||||
|
{
|
||||||
|
// For unknown headers, when header value is empty, RawValueLength will be 0 and
|
||||||
|
// pRawValue will be null.
|
||||||
|
if (pUnknownHeader->pName != null && pUnknownHeader->NameLength > 0)
|
||||||
|
{
|
||||||
|
var headerName = HeaderEncoding.GetString(pUnknownHeader->pName + fixup, pUnknownHeader->NameLength);
|
||||||
|
string headerValue;
|
||||||
|
if (pUnknownHeader->pRawValue != null && pUnknownHeader->RawValueLength > 0)
|
||||||
|
{
|
||||||
|
headerValue = HeaderEncoding.GetString(pUnknownHeader->pRawValue + fixup, pUnknownHeader->RawValueLength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
headerValue = string.Empty;
|
||||||
|
}
|
||||||
|
// Note that Http.Sys currently collapses all headers of the same name to a single coma separated string,
|
||||||
|
// so we can just call Set.
|
||||||
|
unknownHeaders[headerName] = headerValue;
|
||||||
|
}
|
||||||
|
pUnknownHeader++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal SocketAddress GetRemoteEndPoint()
|
||||||
|
{
|
||||||
|
return GetEndPoint(localEndpoint: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal SocketAddress GetLocalEndPoint()
|
||||||
|
{
|
||||||
|
return GetEndPoint(localEndpoint: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SocketAddress GetEndPoint(bool localEndpoint)
|
||||||
|
{
|
||||||
|
if (_permanentlyPinned)
|
||||||
|
{
|
||||||
|
return GetEndPointHelper(localEndpoint, _nativeRequest, (byte *)0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fixed (byte* pMemoryBlob = _backingBuffer)
|
||||||
|
{
|
||||||
|
var request = (HttpApiTypes.HTTP_REQUEST*)(pMemoryBlob + _bufferAlignment);
|
||||||
|
return GetEndPointHelper(localEndpoint, request, pMemoryBlob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SocketAddress GetEndPointHelper(bool localEndpoint, HttpApiTypes.HTTP_REQUEST* request, byte* pMemoryBlob)
|
||||||
|
{
|
||||||
|
var source = localEndpoint ? (byte*)request->Address.pLocalAddress : (byte*)request->Address.pRemoteAddress;
|
||||||
|
|
||||||
|
if (source == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var address = (IntPtr)(pMemoryBlob + _bufferAlignment - (byte*)_originalBufferAddress + source);
|
||||||
|
return CopyOutAddress(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SocketAddress CopyOutAddress(IntPtr address)
|
||||||
|
{
|
||||||
|
ushort addressFamily = *((ushort*)address);
|
||||||
|
if (addressFamily == (ushort)AddressFamily.InterNetwork)
|
||||||
|
{
|
||||||
|
var v4address = new SocketAddress(AddressFamily.InterNetwork, SocketAddress.IPv4AddressSize);
|
||||||
|
fixed (byte* pBuffer = v4address.Buffer)
|
||||||
|
{
|
||||||
|
for (int index = 2; index < SocketAddress.IPv4AddressSize; index++)
|
||||||
|
{
|
||||||
|
pBuffer[index] = ((byte*)address)[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v4address;
|
||||||
|
}
|
||||||
|
if (addressFamily == (ushort)AddressFamily.InterNetworkV6)
|
||||||
|
{
|
||||||
|
var v6address = new SocketAddress(AddressFamily.InterNetworkV6, SocketAddress.IPv6AddressSize);
|
||||||
|
fixed (byte* pBuffer = v6address.Buffer)
|
||||||
|
{
|
||||||
|
for (int index = 2; index < SocketAddress.IPv6AddressSize; index++)
|
||||||
|
{
|
||||||
|
pBuffer[index] = ((byte*)address)[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v6address;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal uint GetChunks(ref int dataChunkIndex, ref uint dataChunkOffset, byte[] buffer, int offset, int size)
|
||||||
|
{
|
||||||
|
// Return value.
|
||||||
|
if (_permanentlyPinned)
|
||||||
|
{
|
||||||
|
return GetChunksHelper(ref dataChunkIndex, ref dataChunkOffset, buffer, offset, size, 0, _nativeRequest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fixed (byte* pMemoryBlob = _backingBuffer)
|
||||||
|
{
|
||||||
|
var request = (HttpApiTypes.HTTP_REQUEST*)(pMemoryBlob + _bufferAlignment);
|
||||||
|
long fixup = pMemoryBlob - (byte*)_originalBufferAddress;
|
||||||
|
return GetChunksHelper(ref dataChunkIndex, ref dataChunkOffset, buffer, offset, size, fixup, request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint GetChunksHelper(ref int dataChunkIndex, ref uint dataChunkOffset, byte[] buffer, int offset, int size, long fixup, HttpApiTypes.HTTP_REQUEST* request)
|
||||||
|
{
|
||||||
|
uint dataRead = 0;
|
||||||
|
|
||||||
|
if (request->EntityChunkCount > 0 && dataChunkIndex < request->EntityChunkCount && dataChunkIndex != -1)
|
||||||
|
{
|
||||||
|
var pDataChunk = (HttpApiTypes.HTTP_DATA_CHUNK*)(fixup + (byte*)&request->pEntityChunks[dataChunkIndex]);
|
||||||
|
|
||||||
|
fixed (byte* pReadBuffer = buffer)
|
||||||
|
{
|
||||||
|
byte* pTo = &pReadBuffer[offset];
|
||||||
|
|
||||||
|
while (dataChunkIndex < request->EntityChunkCount && dataRead < size)
|
||||||
|
{
|
||||||
|
if (dataChunkOffset >= pDataChunk->fromMemory.BufferLength)
|
||||||
|
{
|
||||||
|
dataChunkOffset = 0;
|
||||||
|
dataChunkIndex++;
|
||||||
|
pDataChunk++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byte* pFrom = (byte*)pDataChunk->fromMemory.pBuffer + dataChunkOffset + fixup;
|
||||||
|
|
||||||
|
uint bytesToRead = pDataChunk->fromMemory.BufferLength - (uint)dataChunkOffset;
|
||||||
|
if (bytesToRead > (uint)size)
|
||||||
|
{
|
||||||
|
bytesToRead = (uint)size;
|
||||||
|
}
|
||||||
|
for (uint i = 0; i < bytesToRead; i++)
|
||||||
|
{
|
||||||
|
*(pTo++) = *(pFrom++);
|
||||||
|
}
|
||||||
|
dataRead += bytesToRead;
|
||||||
|
dataChunkOffset += bytesToRead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// we're finished.
|
||||||
|
if (dataChunkIndex == request->EntityChunkCount)
|
||||||
|
{
|
||||||
|
dataChunkIndex = -1;
|
||||||
|
}
|
||||||
|
return dataRead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal static class RawUrlHelper
|
internal static class RawUrlHelper
|
||||||
{
|
{
|
||||||
|
|
@ -11,7 +11,7 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
[GeneratedCode("TextTemplatingFileGenerator", "")]
|
[GeneratedCode("TextTemplatingFileGenerator", "")]
|
||||||
internal partial class RequestHeaders
|
internal partial class RequestHeaders
|
||||||
|
|
@ -6,20 +6,26 @@ using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
|
using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal partial class RequestHeaders : IDictionary<string, StringValues>
|
internal partial class RequestHeaders : IHeaderDictionary
|
||||||
{
|
{
|
||||||
private IDictionary<string, StringValues> _extra;
|
private IDictionary<string, StringValues> _extra;
|
||||||
private NativeRequestContext _requestMemoryBlob;
|
private NativeRequestContext _requestMemoryBlob;
|
||||||
|
private long? _contentLength;
|
||||||
|
private StringValues _contentLengthText;
|
||||||
|
|
||||||
internal RequestHeaders(NativeRequestContext requestMemoryBlob)
|
internal RequestHeaders(NativeRequestContext requestMemoryBlob)
|
||||||
{
|
{
|
||||||
_requestMemoryBlob = requestMemoryBlob;
|
_requestMemoryBlob = requestMemoryBlob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsReadOnly { get; internal set; }
|
||||||
|
|
||||||
private IDictionary<string, StringValues> Extra
|
private IDictionary<string, StringValues> Extra
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -43,6 +49,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
ThrowIfReadOnly();
|
||||||
if (!PropertiesTrySetValue(key, value))
|
if (!PropertiesTrySetValue(key, value))
|
||||||
{
|
{
|
||||||
Extra[key] = value;
|
Extra[key] = value;
|
||||||
|
|
@ -131,6 +138,96 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
get { return false; }
|
get { return false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long? IHeaderDictionary.ContentLength
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
long value;
|
||||||
|
var rawValue = this[HttpKnownHeaderNames.ContentLength];
|
||||||
|
|
||||||
|
if (_contentLengthText.Equals(rawValue))
|
||||||
|
{
|
||||||
|
return _contentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawValue.Count == 1 &&
|
||||||
|
!string.IsNullOrWhiteSpace(rawValue[0]) &&
|
||||||
|
HeaderUtilities.TryParseNonNegativeInt64(new StringSegment(rawValue[0]).Trim(), out value))
|
||||||
|
{
|
||||||
|
_contentLengthText = rawValue;
|
||||||
|
_contentLength = value;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
ThrowIfReadOnly();
|
||||||
|
|
||||||
|
if (value.HasValue)
|
||||||
|
{
|
||||||
|
if (value.Value < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("value", value.Value, "Cannot be negative.");
|
||||||
|
}
|
||||||
|
_contentLengthText = HeaderUtilities.FormatNonNegativeInt64(value.Value);
|
||||||
|
this[HttpKnownHeaderNames.ContentLength] = _contentLengthText;
|
||||||
|
_contentLength = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Remove(HttpKnownHeaderNames.ContentLength);
|
||||||
|
_contentLengthText = StringValues.Empty;
|
||||||
|
_contentLength = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringValues this[string key]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
StringValues values;
|
||||||
|
return TryGetValue(key, out values) ? values : StringValues.Empty;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (StringValues.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
Remove(key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Extra[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringValues IHeaderDictionary.this[string key]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (PropertiesTryGetValue(key, out var value))
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Extra.TryGetValue(key, out value))
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return StringValues.Empty;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!PropertiesTrySetValue(key, value))
|
||||||
|
{
|
||||||
|
Extra[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool ICollection<KeyValuePair<string, StringValues>>.Remove(KeyValuePair<string, StringValues> item)
|
bool ICollection<KeyValuePair<string, StringValues>>.Remove(KeyValuePair<string, StringValues> item)
|
||||||
{
|
{
|
||||||
return ((IDictionary<string, StringValues>)this).Contains(item) &&
|
return ((IDictionary<string, StringValues>)this).Contains(item) &&
|
||||||
|
|
@ -146,5 +243,23 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
return ((IDictionary<string, StringValues>)this).GetEnumerator();
|
return ((IDictionary<string, StringValues>)this).GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ThrowIfReadOnly()
|
||||||
|
{
|
||||||
|
if (IsReadOnly)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("The response headers cannot be modified because the response has already started.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> GetValues(string key)
|
||||||
|
{
|
||||||
|
StringValues values;
|
||||||
|
if (TryGetValue(key, out values))
|
||||||
|
{
|
||||||
|
return HeaderParser.SplitValues(values);
|
||||||
|
}
|
||||||
|
return HeaderParser.Empty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
// We don't use the cooked URL because http.sys unescapes all percent-encoded values. However,
|
// We don't use the cooked URL because http.sys unescapes all percent-encoded values. However,
|
||||||
// we also can't just use the raw Uri, since http.sys supports not only UTF-8, but also ANSI/DBCS and
|
// we also can't just use the raw Uri, since http.sys supports not only UTF-8, but also ANSI/DBCS and
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.HttpSys.Internal
|
||||||
{
|
{
|
||||||
internal enum SslStatus : byte
|
internal enum SslStatus : byte
|
||||||
{
|
{
|
||||||
|
|
@ -3,9 +3,10 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Diagnostics.Contracts;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
|
|
@ -16,12 +17,14 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
private TaskCompletionSource<RequestContext> _tcs;
|
private TaskCompletionSource<RequestContext> _tcs;
|
||||||
private HttpSysListener _server;
|
private HttpSysListener _server;
|
||||||
private NativeRequestContext _nativeRequestContext;
|
private NativeRequestContext _nativeRequestContext;
|
||||||
|
private const int DefaultBufferSize = 4096;
|
||||||
|
private const int AlignmentPadding = 8;
|
||||||
|
|
||||||
internal AsyncAcceptContext(HttpSysListener server)
|
internal AsyncAcceptContext(HttpSysListener server)
|
||||||
{
|
{
|
||||||
_server = server;
|
_server = server;
|
||||||
_tcs = new TaskCompletionSource<RequestContext>();
|
_tcs = new TaskCompletionSource<RequestContext>();
|
||||||
_nativeRequestContext = new NativeRequestContext(this);
|
AllocateNativeRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Task<RequestContext> Task
|
internal Task<RequestContext> Task
|
||||||
|
|
@ -68,12 +71,10 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
// at this point we have received an unmanaged HTTP_REQUEST and memoryBlob
|
// at this point we have received an unmanaged HTTP_REQUEST and memoryBlob
|
||||||
// points to it we need to hook up our authentication handling code here.
|
// points to it we need to hook up our authentication handling code here.
|
||||||
bool stoleBlob = false;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (server.ValidateRequest(asyncResult._nativeRequestContext) && server.ValidateAuth(asyncResult._nativeRequestContext))
|
if (server.ValidateRequest(asyncResult._nativeRequestContext) && server.ValidateAuth(asyncResult._nativeRequestContext))
|
||||||
{
|
{
|
||||||
stoleBlob = true;
|
|
||||||
RequestContext requestContext = new RequestContext(server, asyncResult._nativeRequestContext);
|
RequestContext requestContext = new RequestContext(server, asyncResult._nativeRequestContext);
|
||||||
asyncResult.Tcs.TrySetResult(requestContext);
|
asyncResult.Tcs.TrySetResult(requestContext);
|
||||||
complete = true;
|
complete = true;
|
||||||
|
|
@ -81,20 +82,21 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (stoleBlob)
|
// The request has been handed to the user, which means this code can't reuse the blob. Reset it here.
|
||||||
|
if (complete)
|
||||||
{
|
{
|
||||||
// The request has been handed to the user, which means this code can't reuse the blob. Reset it here.
|
asyncResult._nativeRequestContext = null;
|
||||||
asyncResult._nativeRequestContext = complete ? null : new NativeRequestContext(asyncResult);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
asyncResult._nativeRequestContext.Reset();
|
asyncResult.AllocateNativeRequest(size: asyncResult._nativeRequestContext.Size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
asyncResult._nativeRequestContext.Reset(asyncResult._nativeRequestContext.RequestId, numBytes);
|
// (uint)backingBuffer.Length - AlignmentPadding
|
||||||
|
asyncResult.AllocateNativeRequest(numBytes, asyncResult._nativeRequestContext.RequestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to issue a new request, either because auth failed, or because our buffer was too small the first time.
|
// We need to issue a new request, either because auth failed, or because our buffer was too small the first time.
|
||||||
|
|
@ -147,7 +149,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
statusCode = HttpApi.HttpReceiveHttpRequest(
|
statusCode = HttpApi.HttpReceiveHttpRequest(
|
||||||
Server.RequestQueue.Handle,
|
Server.RequestQueue.Handle,
|
||||||
_nativeRequestContext.RequestId,
|
_nativeRequestContext.RequestId,
|
||||||
(uint)HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY,
|
(uint)HttpApiTypes.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY,
|
||||||
_nativeRequestContext.NativeRequest,
|
_nativeRequestContext.NativeRequest,
|
||||||
_nativeRequestContext.Size,
|
_nativeRequestContext.Size,
|
||||||
&bytesTransferred,
|
&bytesTransferred,
|
||||||
|
|
@ -165,7 +167,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
// the buffer was not big enough to fit the headers, we need
|
// the buffer was not big enough to fit the headers, we need
|
||||||
// to read the RequestId returned, allocate a new buffer of the required size
|
// to read the RequestId returned, allocate a new buffer of the required size
|
||||||
_nativeRequestContext.Reset(_nativeRequestContext.RequestId, bytesTransferred);
|
// (uint)backingBuffer.Length - AlignmentPadding
|
||||||
|
AllocateNativeRequest(bytesTransferred);
|
||||||
retry = true;
|
retry = true;
|
||||||
}
|
}
|
||||||
else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS
|
else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS
|
||||||
|
|
@ -179,6 +182,36 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
return statusCode;
|
return statusCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void AllocateNativeRequest(uint? size = null, ulong requestId = 0)
|
||||||
|
{
|
||||||
|
//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));
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
public object AsyncState
|
public object AsyncState
|
||||||
{
|
{
|
||||||
get { return _tcs.Task.AsyncState; }
|
get { return _tcs.Task.AsyncState; }
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
@ -21,7 +22,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
public sealed class AuthenticationManager
|
public sealed class AuthenticationManager
|
||||||
{
|
{
|
||||||
private static readonly int AuthInfoSize =
|
private static readonly int AuthInfoSize =
|
||||||
Marshal.SizeOf<HttpApi.HTTP_SERVER_AUTHENTICATION_INFO>();
|
Marshal.SizeOf<HttpApiTypes.HTTP_SERVER_AUTHENTICATION_INFO>();
|
||||||
|
|
||||||
private UrlGroup _urlGroup;
|
private UrlGroup _urlGroup;
|
||||||
private AuthenticationSchemes _authSchemes;
|
private AuthenticationSchemes _authSchemes;
|
||||||
|
|
@ -62,12 +63,12 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpApi.HTTP_SERVER_AUTHENTICATION_INFO authInfo =
|
HttpApiTypes.HTTP_SERVER_AUTHENTICATION_INFO authInfo =
|
||||||
new HttpApi.HTTP_SERVER_AUTHENTICATION_INFO();
|
new HttpApiTypes.HTTP_SERVER_AUTHENTICATION_INFO();
|
||||||
|
|
||||||
authInfo.Flags = HttpApi.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT;
|
authInfo.Flags = HttpApiTypes.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT;
|
||||||
var authSchemes = (HttpApi.HTTP_AUTH_TYPES)_authSchemes;
|
var authSchemes = (HttpApiTypes.HTTP_AUTH_TYPES)_authSchemes;
|
||||||
if (authSchemes != HttpApi.HTTP_AUTH_TYPES.NONE)
|
if (authSchemes != HttpApiTypes.HTTP_AUTH_TYPES.NONE)
|
||||||
{
|
{
|
||||||
authInfo.AuthSchemes = authSchemes;
|
authInfo.AuthSchemes = authSchemes;
|
||||||
|
|
||||||
|
|
@ -81,7 +82,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
IntPtr infoptr = new IntPtr(&authInfo);
|
IntPtr infoptr = new IntPtr(&authInfo);
|
||||||
|
|
||||||
_urlGroup.SetProperty(
|
_urlGroup.SetProperty(
|
||||||
HttpApi.HTTP_SERVER_PROPERTY.HttpServerAuthenticationProperty,
|
HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerAuthenticationProperty,
|
||||||
infoptr, (uint)AuthInfoSize);
|
infoptr, (uint)AuthInfoSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
@ -56,7 +57,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
throw new PlatformNotSupportedException();
|
throw new PlatformNotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(HttpApi.ApiVersion == HttpApi.HTTP_API_VERSION.Version20, "Invalid Http api version");
|
Debug.Assert(HttpApi.ApiVersion == HttpApiTypes.HTTP_API_VERSION.Version20, "Invalid Http api version");
|
||||||
|
|
||||||
Options = options;
|
Options = options;
|
||||||
|
|
||||||
|
|
@ -317,8 +318,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
||||||
private unsafe void SendError(ulong requestId, int httpStatusCode, IList<string> authChallenges)
|
private unsafe void SendError(ulong requestId, int httpStatusCode, IList<string> authChallenges)
|
||||||
{
|
{
|
||||||
HttpApi.HTTP_RESPONSE_V2 httpResponse = new HttpApi.HTTP_RESPONSE_V2();
|
HttpApiTypes.HTTP_RESPONSE_V2 httpResponse = new HttpApiTypes.HTTP_RESPONSE_V2();
|
||||||
httpResponse.Response_V1.Version = new HttpApi.HTTP_VERSION();
|
httpResponse.Response_V1.Version = new HttpApiTypes.HTTP_VERSION();
|
||||||
httpResponse.Response_V1.Version.MajorVersion = (ushort)1;
|
httpResponse.Response_V1.Version.MajorVersion = (ushort)1;
|
||||||
httpResponse.Response_V1.Version.MinorVersion = (ushort)1;
|
httpResponse.Response_V1.Version.MinorVersion = (ushort)1;
|
||||||
|
|
||||||
|
|
@ -331,25 +332,25 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
pinnedHeaders = new List<GCHandle>();
|
pinnedHeaders = new List<GCHandle>();
|
||||||
|
|
||||||
HttpApi.HTTP_RESPONSE_INFO[] knownHeaderInfo = null;
|
HttpApiTypes.HTTP_RESPONSE_INFO[] knownHeaderInfo = null;
|
||||||
knownHeaderInfo = new HttpApi.HTTP_RESPONSE_INFO[1];
|
knownHeaderInfo = new HttpApiTypes.HTTP_RESPONSE_INFO[1];
|
||||||
gcHandle = GCHandle.Alloc(knownHeaderInfo, GCHandleType.Pinned);
|
gcHandle = GCHandle.Alloc(knownHeaderInfo, GCHandleType.Pinned);
|
||||||
pinnedHeaders.Add(gcHandle);
|
pinnedHeaders.Add(gcHandle);
|
||||||
httpResponse.pResponseInfo = (HttpApi.HTTP_RESPONSE_INFO*)gcHandle.AddrOfPinnedObject();
|
httpResponse.pResponseInfo = (HttpApiTypes.HTTP_RESPONSE_INFO*)gcHandle.AddrOfPinnedObject();
|
||||||
|
|
||||||
knownHeaderInfo[httpResponse.ResponseInfoCount].Type = HttpApi.HTTP_RESPONSE_INFO_TYPE.HttpResponseInfoTypeMultipleKnownHeaders;
|
knownHeaderInfo[httpResponse.ResponseInfoCount].Type = HttpApiTypes.HTTP_RESPONSE_INFO_TYPE.HttpResponseInfoTypeMultipleKnownHeaders;
|
||||||
knownHeaderInfo[httpResponse.ResponseInfoCount].Length =
|
knownHeaderInfo[httpResponse.ResponseInfoCount].Length =
|
||||||
(uint)Marshal.SizeOf<HttpApi.HTTP_MULTIPLE_KNOWN_HEADERS>();
|
(uint)Marshal.SizeOf<HttpApiTypes.HTTP_MULTIPLE_KNOWN_HEADERS>();
|
||||||
|
|
||||||
HttpApi.HTTP_MULTIPLE_KNOWN_HEADERS header = new HttpApi.HTTP_MULTIPLE_KNOWN_HEADERS();
|
HttpApiTypes.HTTP_MULTIPLE_KNOWN_HEADERS header = new HttpApiTypes.HTTP_MULTIPLE_KNOWN_HEADERS();
|
||||||
|
|
||||||
header.HeaderId = HttpApi.HTTP_RESPONSE_HEADER_ID.Enum.HttpHeaderWwwAuthenticate;
|
header.HeaderId = HttpApiTypes.HTTP_RESPONSE_HEADER_ID.Enum.HttpHeaderWwwAuthenticate;
|
||||||
header.Flags = HttpApi.HTTP_RESPONSE_INFO_FLAGS.PreserveOrder; // The docs say this is for www-auth only.
|
header.Flags = HttpApiTypes.HTTP_RESPONSE_INFO_FLAGS.PreserveOrder; // The docs say this is for www-auth only.
|
||||||
|
|
||||||
HttpApi.HTTP_KNOWN_HEADER[] nativeHeaderValues = new HttpApi.HTTP_KNOWN_HEADER[authChallenges.Count];
|
HttpApiTypes.HTTP_KNOWN_HEADER[] nativeHeaderValues = new HttpApiTypes.HTTP_KNOWN_HEADER[authChallenges.Count];
|
||||||
gcHandle = GCHandle.Alloc(nativeHeaderValues, GCHandleType.Pinned);
|
gcHandle = GCHandle.Alloc(nativeHeaderValues, GCHandleType.Pinned);
|
||||||
pinnedHeaders.Add(gcHandle);
|
pinnedHeaders.Add(gcHandle);
|
||||||
header.KnownHeaders = (HttpApi.HTTP_KNOWN_HEADER*)gcHandle.AddrOfPinnedObject();
|
header.KnownHeaders = (HttpApiTypes.HTTP_KNOWN_HEADER*)gcHandle.AddrOfPinnedObject();
|
||||||
|
|
||||||
for (int headerValueIndex = 0; headerValueIndex < authChallenges.Count; headerValueIndex++)
|
for (int headerValueIndex = 0; headerValueIndex < authChallenges.Count; headerValueIndex++)
|
||||||
{
|
{
|
||||||
|
|
@ -359,14 +360,14 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
nativeHeaderValues[header.KnownHeaderCount].RawValueLength = (ushort)bytes.Length;
|
nativeHeaderValues[header.KnownHeaderCount].RawValueLength = (ushort)bytes.Length;
|
||||||
gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
||||||
pinnedHeaders.Add(gcHandle);
|
pinnedHeaders.Add(gcHandle);
|
||||||
nativeHeaderValues[header.KnownHeaderCount].pRawValue = (sbyte*)gcHandle.AddrOfPinnedObject();
|
nativeHeaderValues[header.KnownHeaderCount].pRawValue = (byte*)gcHandle.AddrOfPinnedObject();
|
||||||
header.KnownHeaderCount++;
|
header.KnownHeaderCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This type is a struct, not an object, so pinning it causes a boxed copy to be created. We can't do that until after all the fields are set.
|
// This type is a struct, not an object, so pinning it causes a boxed copy to be created. We can't do that until after all the fields are set.
|
||||||
gcHandle = GCHandle.Alloc(header, GCHandleType.Pinned);
|
gcHandle = GCHandle.Alloc(header, GCHandleType.Pinned);
|
||||||
pinnedHeaders.Add(gcHandle);
|
pinnedHeaders.Add(gcHandle);
|
||||||
knownHeaderInfo[0].pInfo = (HttpApi.HTTP_MULTIPLE_KNOWN_HEADERS*)gcHandle.AddrOfPinnedObject();
|
knownHeaderInfo[0].pInfo = (HttpApiTypes.HTTP_MULTIPLE_KNOWN_HEADERS*)gcHandle.AddrOfPinnedObject();
|
||||||
|
|
||||||
httpResponse.ResponseInfoCount = 1;
|
httpResponse.ResponseInfoCount = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -378,13 +379,13 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
byte[] byteReason = HeaderEncoding.GetBytes(statusDescription);
|
byte[] byteReason = HeaderEncoding.GetBytes(statusDescription);
|
||||||
fixed (byte* pReason = byteReason)
|
fixed (byte* pReason = byteReason)
|
||||||
{
|
{
|
||||||
httpResponse.Response_V1.pReason = (sbyte*)pReason;
|
httpResponse.Response_V1.pReason = (byte*)pReason;
|
||||||
httpResponse.Response_V1.ReasonLength = (ushort)byteReason.Length;
|
httpResponse.Response_V1.ReasonLength = (ushort)byteReason.Length;
|
||||||
|
|
||||||
byte[] byteContentLength = new byte[] { (byte)'0' };
|
byte[] byteContentLength = new byte[] { (byte)'0' };
|
||||||
fixed (byte* pContentLength = byteContentLength)
|
fixed (byte* pContentLength = byteContentLength)
|
||||||
{
|
{
|
||||||
(&httpResponse.Response_V1.Headers.KnownHeaders)[(int)HttpSysResponseHeader.ContentLength].pRawValue = (sbyte*)pContentLength;
|
(&httpResponse.Response_V1.Headers.KnownHeaders)[(int)HttpSysResponseHeader.ContentLength].pRawValue = (byte*)pContentLength;
|
||||||
(&httpResponse.Response_V1.Headers.KnownHeaders)[(int)HttpSysResponseHeader.ContentLength].RawValueLength = (ushort)byteContentLength.Length;
|
(&httpResponse.Response_V1.Headers.KnownHeaders)[(int)HttpSysResponseHeader.ContentLength].RawValueLength = (ushort)byteContentLength.Length;
|
||||||
httpResponse.Response_V1.Headers.UnknownHeaderCount = 0;
|
httpResponse.Response_V1.Headers.UnknownHeaderCount = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,10 @@
|
||||||
<PackageTags>aspnetcore;weblistener;httpsys</PackageTags>
|
<PackageTags>aspnetcore;weblistener;httpsys</PackageTags>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\..\shared\Microsoft.AspNetCore.HttpSys.Sources\**\*.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Core" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.Core" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Hosting" />
|
<PackageReference Include="Microsoft.AspNetCore.Hosting" />
|
||||||
|
|
|
||||||
|
|
@ -1,168 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
|
||||||
{
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>
|
|
||||||
/// Specifies the address families.
|
|
||||||
/// </para>
|
|
||||||
/// </devdoc>
|
|
||||||
internal enum AddressFamily
|
|
||||||
{
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Unknown = -1, // Unknown
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Unspecified = 0, // unspecified
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Unix = 1, // local to host (pipes, portals)
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
InterNetwork = 2, // internetwork: UDP, TCP, etc.
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
ImpLink = 3, // arpanet imp addresses
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Pup = 4, // pup protocols: e.g. BSP
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Chaos = 5, // mit CHAOS protocols
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
NS = 6, // XEROX NS protocols
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Ipx = NS, // IPX and SPX
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Iso = 7, // ISO protocols
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Osi = Iso, // OSI is ISO
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Ecma = 8, // european computer manufacturers
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
DataKit = 9, // datakit protocols
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Ccitt = 10, // CCITT protocols, X.25 etc
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Sna = 11, // IBM SNA
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
DecNet = 12, // DECnet
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
DataLink = 13, // Direct data link interface
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Lat = 14, // LAT
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
HyperChannel = 15, // NSC Hyperchannel
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
AppleTalk = 16, // AppleTalk
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
NetBios = 17, // NetBios-style addresses
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
VoiceView = 18, // VoiceView
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
FireFox = 19, // FireFox
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Banyan = 21, // Banyan
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Atm = 22, // Native ATM Services
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
InterNetworkV6 = 23, // Internetwork Version 6
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Cluster = 24, // Microsoft Wolfpack
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Ieee12844 = 25, // IEEE 1284.4 WG AF
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Irda = 26, // IrDA
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
NetworkDesigners = 28, // Network Designers OSI & gateway enabled protocols
|
|
||||||
|
|
||||||
/// <devdoc>
|
|
||||||
/// <para>[To be supplied.]</para>
|
|
||||||
/// </devdoc>
|
|
||||||
Max = 29, // Max
|
|
||||||
}; // enum AddressFamily
|
|
||||||
}
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Collections.Concurrent;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
|
using static Microsoft.AspNetCore.HttpSys.Internal.HttpApiTypes;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
|
|
@ -70,688 +70,6 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
[DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
|
[DllImport(HTTPAPI, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
|
||||||
internal static extern unsafe uint HttpCloseRequestQueue(IntPtr pReqQueueHandle);
|
internal static extern unsafe uint HttpCloseRequestQueue(IntPtr pReqQueueHandle);
|
||||||
|
|
||||||
internal enum HTTP_API_VERSION
|
|
||||||
{
|
|
||||||
Invalid,
|
|
||||||
Version10,
|
|
||||||
Version20,
|
|
||||||
}
|
|
||||||
|
|
||||||
// see http.w for definitions
|
|
||||||
internal enum HTTP_SERVER_PROPERTY
|
|
||||||
{
|
|
||||||
HttpServerAuthenticationProperty,
|
|
||||||
HttpServerLoggingProperty,
|
|
||||||
HttpServerQosProperty,
|
|
||||||
HttpServerTimeoutsProperty,
|
|
||||||
HttpServerQueueLengthProperty,
|
|
||||||
HttpServerStateProperty,
|
|
||||||
HttpServer503VerbosityProperty,
|
|
||||||
HttpServerBindingProperty,
|
|
||||||
HttpServerExtendedAuthenticationProperty,
|
|
||||||
HttpServerListenEndpointProperty,
|
|
||||||
HttpServerChannelBindProperty,
|
|
||||||
HttpServerProtectionLevelProperty,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Currently only one request info type is supported but the enum is for future extensibility.
|
|
||||||
|
|
||||||
internal enum HTTP_REQUEST_INFO_TYPE
|
|
||||||
{
|
|
||||||
HttpRequestInfoTypeAuth,
|
|
||||||
HttpRequestInfoTypeChannelBind,
|
|
||||||
HttpRequestInfoTypeSslProtocol,
|
|
||||||
HttpRequestInfoTypeSslTokenBinding
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum HTTP_RESPONSE_INFO_TYPE
|
|
||||||
{
|
|
||||||
HttpResponseInfoTypeMultipleKnownHeaders,
|
|
||||||
HttpResponseInfoTypeAuthenticationProperty,
|
|
||||||
HttpResponseInfoTypeQosProperty,
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum HTTP_TIMEOUT_TYPE
|
|
||||||
{
|
|
||||||
EntityBody,
|
|
||||||
DrainEntityBody,
|
|
||||||
RequestQueue,
|
|
||||||
IdleConnection,
|
|
||||||
HeaderWait,
|
|
||||||
MinSendRate,
|
|
||||||
}
|
|
||||||
|
|
||||||
internal const int MaxTimeout = 6;
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_VERSION
|
|
||||||
{
|
|
||||||
internal ushort MajorVersion;
|
|
||||||
internal ushort MinorVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_KNOWN_HEADER
|
|
||||||
{
|
|
||||||
internal ushort RawValueLength;
|
|
||||||
internal sbyte* pRawValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit)]
|
|
||||||
internal struct HTTP_DATA_CHUNK
|
|
||||||
{
|
|
||||||
[FieldOffset(0)]
|
|
||||||
internal HTTP_DATA_CHUNK_TYPE DataChunkType;
|
|
||||||
|
|
||||||
[FieldOffset(8)]
|
|
||||||
internal FromMemory fromMemory;
|
|
||||||
|
|
||||||
[FieldOffset(8)]
|
|
||||||
internal FromFileHandle fromFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct FromMemory
|
|
||||||
{
|
|
||||||
// 4 bytes for 32bit, 8 bytes for 64bit
|
|
||||||
internal IntPtr pBuffer;
|
|
||||||
internal uint BufferLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct FromFileHandle
|
|
||||||
{
|
|
||||||
internal ulong offset;
|
|
||||||
internal ulong count;
|
|
||||||
internal IntPtr fileHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTPAPI_VERSION
|
|
||||||
{
|
|
||||||
internal ushort HttpApiMajorVersion;
|
|
||||||
internal ushort HttpApiMinorVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_COOKED_URL
|
|
||||||
{
|
|
||||||
internal ushort FullUrlLength;
|
|
||||||
internal ushort HostLength;
|
|
||||||
internal ushort AbsPathLength;
|
|
||||||
internal ushort QueryStringLength;
|
|
||||||
internal ushort* pFullUrl;
|
|
||||||
internal ushort* pHost;
|
|
||||||
internal ushort* pAbsPath;
|
|
||||||
internal ushort* pQueryString;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only cache unauthorized GETs + HEADs.
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_CACHE_POLICY
|
|
||||||
{
|
|
||||||
internal HTTP_CACHE_POLICY_TYPE Policy;
|
|
||||||
internal uint SecondsToLive;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum HTTP_CACHE_POLICY_TYPE : int
|
|
||||||
{
|
|
||||||
HttpCachePolicyNocache = 0,
|
|
||||||
HttpCachePolicyUserInvalidates = 1,
|
|
||||||
HttpCachePolicyTimeToLive = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct SOCKADDR
|
|
||||||
{
|
|
||||||
internal ushort sa_family;
|
|
||||||
internal byte sa_data;
|
|
||||||
internal byte sa_data_02;
|
|
||||||
internal byte sa_data_03;
|
|
||||||
internal byte sa_data_04;
|
|
||||||
internal byte sa_data_05;
|
|
||||||
internal byte sa_data_06;
|
|
||||||
internal byte sa_data_07;
|
|
||||||
internal byte sa_data_08;
|
|
||||||
internal byte sa_data_09;
|
|
||||||
internal byte sa_data_10;
|
|
||||||
internal byte sa_data_11;
|
|
||||||
internal byte sa_data_12;
|
|
||||||
internal byte sa_data_13;
|
|
||||||
internal byte sa_data_14;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_TRANSPORT_ADDRESS
|
|
||||||
{
|
|
||||||
internal SOCKADDR* pRemoteAddress;
|
|
||||||
internal SOCKADDR* pLocalAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_SSL_CLIENT_CERT_INFO
|
|
||||||
{
|
|
||||||
internal uint CertFlags;
|
|
||||||
internal uint CertEncodedSize;
|
|
||||||
internal byte* pCertEncoded;
|
|
||||||
internal void* Token;
|
|
||||||
internal byte CertDeniedByMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum HTTP_SERVICE_BINDING_TYPE : uint
|
|
||||||
{
|
|
||||||
HttpServiceBindingTypeNone = 0,
|
|
||||||
HttpServiceBindingTypeW,
|
|
||||||
HttpServiceBindingTypeA
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_SERVICE_BINDING_BASE
|
|
||||||
{
|
|
||||||
internal HTTP_SERVICE_BINDING_TYPE Type;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_REQUEST_CHANNEL_BIND_STATUS
|
|
||||||
{
|
|
||||||
internal IntPtr ServiceName;
|
|
||||||
internal IntPtr ChannelToken;
|
|
||||||
internal uint ChannelTokenSize;
|
|
||||||
internal uint Flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_UNKNOWN_HEADER
|
|
||||||
{
|
|
||||||
internal ushort NameLength;
|
|
||||||
internal ushort RawValueLength;
|
|
||||||
internal sbyte* pName;
|
|
||||||
internal sbyte* pRawValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_SSL_INFO
|
|
||||||
{
|
|
||||||
internal ushort ServerCertKeySize;
|
|
||||||
internal ushort ConnectionKeySize;
|
|
||||||
internal uint ServerCertIssuerSize;
|
|
||||||
internal uint ServerCertSubjectSize;
|
|
||||||
internal sbyte* pServerCertIssuer;
|
|
||||||
internal sbyte* pServerCertSubject;
|
|
||||||
internal HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo;
|
|
||||||
internal uint SslClientCertNegotiated;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_RESPONSE_HEADERS
|
|
||||||
{
|
|
||||||
internal ushort UnknownHeaderCount;
|
|
||||||
internal HTTP_UNKNOWN_HEADER* pUnknownHeaders;
|
|
||||||
internal ushort TrailerCount;
|
|
||||||
internal HTTP_UNKNOWN_HEADER* pTrailers;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_02;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_03;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_04;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_05;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_06;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_07;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_08;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_09;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_10;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_11;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_12;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_13;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_14;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_15;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_16;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_17;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_18;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_19;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_20;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_21;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_22;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_23;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_24;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_25;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_26;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_27;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_28;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_29;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_30;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_REQUEST_HEADERS
|
|
||||||
{
|
|
||||||
internal ushort UnknownHeaderCount;
|
|
||||||
internal HTTP_UNKNOWN_HEADER* pUnknownHeaders;
|
|
||||||
internal ushort TrailerCount;
|
|
||||||
internal HTTP_UNKNOWN_HEADER* pTrailers;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_02;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_03;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_04;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_05;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_06;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_07;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_08;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_09;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_10;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_11;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_12;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_13;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_14;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_15;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_16;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_17;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_18;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_19;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_20;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_21;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_22;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_23;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_24;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_25;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_26;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_27;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_28;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_29;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_30;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_31;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_32;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_33;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_34;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_35;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_36;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_37;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_38;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_39;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_40;
|
|
||||||
internal HTTP_KNOWN_HEADER KnownHeaders_41;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum HTTP_VERB : int
|
|
||||||
{
|
|
||||||
HttpVerbUnparsed = 0,
|
|
||||||
HttpVerbUnknown = 1,
|
|
||||||
HttpVerbInvalid = 2,
|
|
||||||
HttpVerbOPTIONS = 3,
|
|
||||||
HttpVerbGET = 4,
|
|
||||||
HttpVerbHEAD = 5,
|
|
||||||
HttpVerbPOST = 6,
|
|
||||||
HttpVerbPUT = 7,
|
|
||||||
HttpVerbDELETE = 8,
|
|
||||||
HttpVerbTRACE = 9,
|
|
||||||
HttpVerbCONNECT = 10,
|
|
||||||
HttpVerbTRACK = 11,
|
|
||||||
HttpVerbMOVE = 12,
|
|
||||||
HttpVerbCOPY = 13,
|
|
||||||
HttpVerbPROPFIND = 14,
|
|
||||||
HttpVerbPROPPATCH = 15,
|
|
||||||
HttpVerbMKCOL = 16,
|
|
||||||
HttpVerbLOCK = 17,
|
|
||||||
HttpVerbUNLOCK = 18,
|
|
||||||
HttpVerbSEARCH = 19,
|
|
||||||
HttpVerbMaximum = 20,
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static readonly string[] HttpVerbs = new string[]
|
|
||||||
{
|
|
||||||
null,
|
|
||||||
"Unknown",
|
|
||||||
"Invalid",
|
|
||||||
"OPTIONS",
|
|
||||||
"GET",
|
|
||||||
"HEAD",
|
|
||||||
"POST",
|
|
||||||
"PUT",
|
|
||||||
"DELETE",
|
|
||||||
"TRACE",
|
|
||||||
"CONNECT",
|
|
||||||
"TRACK",
|
|
||||||
"MOVE",
|
|
||||||
"COPY",
|
|
||||||
"PROPFIND",
|
|
||||||
"PROPPATCH",
|
|
||||||
"MKCOL",
|
|
||||||
"LOCK",
|
|
||||||
"UNLOCK",
|
|
||||||
"SEARCH",
|
|
||||||
};
|
|
||||||
|
|
||||||
internal enum HTTP_DATA_CHUNK_TYPE : int
|
|
||||||
{
|
|
||||||
HttpDataChunkFromMemory = 0,
|
|
||||||
HttpDataChunkFromFileHandle = 1,
|
|
||||||
HttpDataChunkFromFragmentCache = 2,
|
|
||||||
HttpDataChunkMaximum = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_RESPONSE_INFO
|
|
||||||
{
|
|
||||||
internal HTTP_RESPONSE_INFO_TYPE Type;
|
|
||||||
internal uint Length;
|
|
||||||
internal HTTP_MULTIPLE_KNOWN_HEADERS* pInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_RESPONSE
|
|
||||||
{
|
|
||||||
internal uint Flags;
|
|
||||||
internal HTTP_VERSION Version;
|
|
||||||
internal ushort StatusCode;
|
|
||||||
internal ushort ReasonLength;
|
|
||||||
internal sbyte* pReason;
|
|
||||||
internal HTTP_RESPONSE_HEADERS Headers;
|
|
||||||
internal ushort EntityChunkCount;
|
|
||||||
internal HTTP_DATA_CHUNK* pEntityChunks;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_RESPONSE_V2
|
|
||||||
{
|
|
||||||
internal HTTP_RESPONSE Response_V1;
|
|
||||||
internal ushort ResponseInfoCount;
|
|
||||||
internal HTTP_RESPONSE_INFO* pResponseInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum HTTP_RESPONSE_INFO_FLAGS : uint
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
PreserveOrder = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_MULTIPLE_KNOWN_HEADERS
|
|
||||||
{
|
|
||||||
internal HTTP_RESPONSE_HEADER_ID.Enum HeaderId;
|
|
||||||
internal HTTP_RESPONSE_INFO_FLAGS Flags;
|
|
||||||
internal ushort KnownHeaderCount;
|
|
||||||
internal HTTP_KNOWN_HEADER* KnownHeaders;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_REQUEST_AUTH_INFO
|
|
||||||
{
|
|
||||||
internal HTTP_AUTH_STATUS AuthStatus;
|
|
||||||
internal uint SecStatus;
|
|
||||||
internal uint Flags;
|
|
||||||
internal HTTP_REQUEST_AUTH_TYPE AuthType;
|
|
||||||
internal IntPtr AccessToken;
|
|
||||||
internal uint ContextAttributes;
|
|
||||||
internal uint PackedContextLength;
|
|
||||||
internal uint PackedContextType;
|
|
||||||
internal IntPtr PackedContext;
|
|
||||||
internal uint MutualAuthDataLength;
|
|
||||||
internal char* pMutualAuthData;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_REQUEST_INFO
|
|
||||||
{
|
|
||||||
internal HTTP_REQUEST_INFO_TYPE InfoType;
|
|
||||||
internal uint InfoLength;
|
|
||||||
internal HTTP_REQUEST_AUTH_INFO* pInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_REQUEST
|
|
||||||
{
|
|
||||||
internal uint Flags;
|
|
||||||
internal ulong ConnectionId;
|
|
||||||
internal ulong RequestId;
|
|
||||||
internal ulong UrlContext;
|
|
||||||
internal HTTP_VERSION Version;
|
|
||||||
internal HTTP_VERB Verb;
|
|
||||||
internal ushort UnknownVerbLength;
|
|
||||||
internal ushort RawUrlLength;
|
|
||||||
internal sbyte* pUnknownVerb;
|
|
||||||
internal sbyte* pRawUrl;
|
|
||||||
internal HTTP_COOKED_URL CookedUrl;
|
|
||||||
internal HTTP_TRANSPORT_ADDRESS Address;
|
|
||||||
internal HTTP_REQUEST_HEADERS Headers;
|
|
||||||
internal ulong BytesReceived;
|
|
||||||
internal ushort EntityChunkCount;
|
|
||||||
internal HTTP_DATA_CHUNK* pEntityChunks;
|
|
||||||
internal ulong RawConnectionId;
|
|
||||||
internal HTTP_SSL_INFO* pSslInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_REQUEST_V2
|
|
||||||
{
|
|
||||||
internal HTTP_REQUEST Request;
|
|
||||||
internal ushort RequestInfoCount;
|
|
||||||
internal HTTP_REQUEST_INFO* pRequestInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum HTTP_AUTH_STATUS
|
|
||||||
{
|
|
||||||
HttpAuthStatusSuccess,
|
|
||||||
HttpAuthStatusNotAuthenticated,
|
|
||||||
HttpAuthStatusFailure,
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum HTTP_REQUEST_AUTH_TYPE
|
|
||||||
{
|
|
||||||
HttpRequestAuthTypeNone = 0,
|
|
||||||
HttpRequestAuthTypeBasic,
|
|
||||||
HttpRequestAuthTypeDigest,
|
|
||||||
HttpRequestAuthTypeNTLM,
|
|
||||||
HttpRequestAuthTypeNegotiate,
|
|
||||||
HttpRequestAuthTypeKerberos
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum HTTP_QOS_SETTING_TYPE
|
|
||||||
{
|
|
||||||
HttpQosSettingTypeBandwidth,
|
|
||||||
HttpQosSettingTypeConnectionLimit,
|
|
||||||
HttpQosSettingTypeFlowRate
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_SERVER_AUTHENTICATION_INFO
|
|
||||||
{
|
|
||||||
internal HTTP_FLAGS Flags;
|
|
||||||
internal HTTP_AUTH_TYPES AuthSchemes;
|
|
||||||
internal bool ReceiveMutualAuth;
|
|
||||||
internal bool ReceiveContextHandle;
|
|
||||||
internal bool DisableNTLMCredentialCaching;
|
|
||||||
internal ulong ExFlags;
|
|
||||||
HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS DigestParams;
|
|
||||||
HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS BasicParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS
|
|
||||||
{
|
|
||||||
internal ushort DomainNameLength;
|
|
||||||
internal char* DomainName;
|
|
||||||
internal ushort RealmLength;
|
|
||||||
internal char* Realm;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS
|
|
||||||
{
|
|
||||||
ushort RealmLength;
|
|
||||||
char* Realm;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_REQUEST_TOKEN_BINDING_INFO
|
|
||||||
{
|
|
||||||
public byte* TokenBinding;
|
|
||||||
public uint TokenBindingSize;
|
|
||||||
|
|
||||||
public byte* TlsUnique;
|
|
||||||
public uint TlsUniqueSize;
|
|
||||||
|
|
||||||
public char* KeyType;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_TIMEOUT_LIMIT_INFO
|
|
||||||
{
|
|
||||||
internal HTTP_FLAGS Flags;
|
|
||||||
internal ushort EntityBody;
|
|
||||||
internal ushort DrainEntityBody;
|
|
||||||
internal ushort RequestQueue;
|
|
||||||
internal ushort IdleConnection;
|
|
||||||
internal ushort HeaderWait;
|
|
||||||
internal uint MinSendRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_BINDING_INFO
|
|
||||||
{
|
|
||||||
internal HTTP_FLAGS Flags;
|
|
||||||
internal IntPtr RequestQueueHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_CONNECTION_LIMIT_INFO
|
|
||||||
{
|
|
||||||
internal HTTP_FLAGS Flags;
|
|
||||||
internal uint MaxConnections;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
internal struct HTTP_QOS_SETTING_INFO
|
|
||||||
{
|
|
||||||
internal HTTP_QOS_SETTING_TYPE QosType;
|
|
||||||
internal IntPtr QosSetting;
|
|
||||||
}
|
|
||||||
|
|
||||||
// see http.w for definitions
|
|
||||||
[Flags]
|
|
||||||
internal enum HTTP_FLAGS : uint
|
|
||||||
{
|
|
||||||
NONE = 0x00000000,
|
|
||||||
HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY = 0x00000001,
|
|
||||||
HTTP_RECEIVE_SECURE_CHANNEL_TOKEN = 0x00000001,
|
|
||||||
HTTP_SEND_RESPONSE_FLAG_DISCONNECT = 0x00000001,
|
|
||||||
HTTP_SEND_RESPONSE_FLAG_MORE_DATA = 0x00000002,
|
|
||||||
HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA = 0x00000004,
|
|
||||||
HTTP_SEND_RESPONSE_FLAG_RAW_HEADER = 0x00000004,
|
|
||||||
HTTP_SEND_REQUEST_FLAG_MORE_DATA = 0x00000001,
|
|
||||||
HTTP_PROPERTY_FLAG_PRESENT = 0x00000001,
|
|
||||||
HTTP_INITIALIZE_SERVER = 0x00000001,
|
|
||||||
HTTP_INITIALIZE_CBT = 0x00000004,
|
|
||||||
HTTP_SEND_RESPONSE_FLAG_OPAQUE = 0x00000040,
|
|
||||||
}
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
internal enum HTTP_AUTH_TYPES : uint
|
|
||||||
{
|
|
||||||
NONE = 0x00000000,
|
|
||||||
HTTP_AUTH_ENABLE_BASIC = 0x00000001,
|
|
||||||
HTTP_AUTH_ENABLE_DIGEST = 0x00000002,
|
|
||||||
HTTP_AUTH_ENABLE_NTLM = 0x00000004,
|
|
||||||
HTTP_AUTH_ENABLE_NEGOTIATE = 0x00000008,
|
|
||||||
HTTP_AUTH_ENABLE_KERBEROS = 0x00000010,
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static class HTTP_RESPONSE_HEADER_ID
|
|
||||||
{
|
|
||||||
private static string[] _strings =
|
|
||||||
{
|
|
||||||
"Cache-Control",
|
|
||||||
"Connection",
|
|
||||||
"Date",
|
|
||||||
"Keep-Alive",
|
|
||||||
"Pragma",
|
|
||||||
"Trailer",
|
|
||||||
"Transfer-Encoding",
|
|
||||||
"Upgrade",
|
|
||||||
"Via",
|
|
||||||
"Warning",
|
|
||||||
|
|
||||||
"Allow",
|
|
||||||
"Content-Length",
|
|
||||||
"Content-Type",
|
|
||||||
"Content-Encoding",
|
|
||||||
"Content-Language",
|
|
||||||
"Content-Location",
|
|
||||||
"Content-MD5",
|
|
||||||
"Content-Range",
|
|
||||||
"Expires",
|
|
||||||
"Last-Modified",
|
|
||||||
|
|
||||||
"Accept-Ranges",
|
|
||||||
"Age",
|
|
||||||
"ETag",
|
|
||||||
"Location",
|
|
||||||
"Proxy-Authenticate",
|
|
||||||
"Retry-After",
|
|
||||||
"Server",
|
|
||||||
"Set-Cookie",
|
|
||||||
"Vary",
|
|
||||||
"WWW-Authenticate",
|
|
||||||
};
|
|
||||||
|
|
||||||
private static Dictionary<string, int> _lookupTable = CreateLookupTable();
|
|
||||||
|
|
||||||
private static Dictionary<string, int> CreateLookupTable()
|
|
||||||
{
|
|
||||||
Dictionary<string, int> lookupTable = new Dictionary<string, int>((int)Enum.HttpHeaderResponseMaximum, StringComparer.OrdinalIgnoreCase);
|
|
||||||
for (int i = 0; i < (int)Enum.HttpHeaderResponseMaximum; i++)
|
|
||||||
{
|
|
||||||
lookupTable.Add(_strings[i], i);
|
|
||||||
}
|
|
||||||
return lookupTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static int IndexOfKnownHeader(string HeaderName)
|
|
||||||
{
|
|
||||||
int index;
|
|
||||||
return _lookupTable.TryGetValue(HeaderName, out index) ? index : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum Enum
|
|
||||||
{
|
|
||||||
HttpHeaderCacheControl = 0, // general-header [section 4.5]
|
|
||||||
HttpHeaderConnection = 1, // general-header [section 4.5]
|
|
||||||
HttpHeaderDate = 2, // general-header [section 4.5]
|
|
||||||
HttpHeaderKeepAlive = 3, // general-header [not in rfc]
|
|
||||||
HttpHeaderPragma = 4, // general-header [section 4.5]
|
|
||||||
HttpHeaderTrailer = 5, // general-header [section 4.5]
|
|
||||||
HttpHeaderTransferEncoding = 6, // general-header [section 4.5]
|
|
||||||
HttpHeaderUpgrade = 7, // general-header [section 4.5]
|
|
||||||
HttpHeaderVia = 8, // general-header [section 4.5]
|
|
||||||
HttpHeaderWarning = 9, // general-header [section 4.5]
|
|
||||||
|
|
||||||
HttpHeaderAllow = 10, // entity-header [section 7.1]
|
|
||||||
HttpHeaderContentLength = 11, // entity-header [section 7.1]
|
|
||||||
HttpHeaderContentType = 12, // entity-header [section 7.1]
|
|
||||||
HttpHeaderContentEncoding = 13, // entity-header [section 7.1]
|
|
||||||
HttpHeaderContentLanguage = 14, // entity-header [section 7.1]
|
|
||||||
HttpHeaderContentLocation = 15, // entity-header [section 7.1]
|
|
||||||
HttpHeaderContentMd5 = 16, // entity-header [section 7.1]
|
|
||||||
HttpHeaderContentRange = 17, // entity-header [section 7.1]
|
|
||||||
HttpHeaderExpires = 18, // entity-header [section 7.1]
|
|
||||||
HttpHeaderLastModified = 19, // entity-header [section 7.1]
|
|
||||||
|
|
||||||
// Response Headers
|
|
||||||
|
|
||||||
HttpHeaderAcceptRanges = 20, // response-header [section 6.2]
|
|
||||||
HttpHeaderAge = 21, // response-header [section 6.2]
|
|
||||||
HttpHeaderEtag = 22, // response-header [section 6.2]
|
|
||||||
HttpHeaderLocation = 23, // response-header [section 6.2]
|
|
||||||
HttpHeaderProxyAuthenticate = 24, // response-header [section 6.2]
|
|
||||||
HttpHeaderRetryAfter = 25, // response-header [section 6.2]
|
|
||||||
HttpHeaderServer = 26, // response-header [section 6.2]
|
|
||||||
HttpHeaderSetCookie = 27, // response-header [not in rfc]
|
|
||||||
HttpHeaderVary = 28, // response-header [section 6.2]
|
|
||||||
HttpHeaderWwwAuthenticate = 29, // response-header [section 6.2]
|
|
||||||
|
|
||||||
HttpHeaderResponseMaximum = 30,
|
|
||||||
|
|
||||||
HttpHeaderMaximum = 41
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HTTPAPI_VERSION version;
|
private static HTTPAPI_VERSION version;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using Microsoft.Win32.SafeHandles;
|
using Microsoft.Win32.SafeHandles;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using Microsoft.Win32.SafeHandles;
|
using Microsoft.Win32.SafeHandles;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
@ -17,7 +18,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
serverSessionId = id;
|
serverSessionId = id;
|
||||||
|
|
||||||
// This class uses no real handle so we need to set a dummy handle. Otherwise, IsInvalid always remains
|
// This class uses no real handle so we need to set a dummy handle. Otherwise, IsInvalid always remains
|
||||||
// true.
|
// true.
|
||||||
|
|
||||||
SetHandle(new IntPtr(1));
|
SetHandle(new IntPtr(1));
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
@ -11,7 +12,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
internal class RequestQueue
|
internal class RequestQueue
|
||||||
{
|
{
|
||||||
private static readonly int BindingInfoSize =
|
private static readonly int BindingInfoSize =
|
||||||
Marshal.SizeOf<HttpApi.HTTP_BINDING_INFO>();
|
Marshal.SizeOf<HttpApiTypes.HTTP_BINDING_INFO>();
|
||||||
|
|
||||||
private readonly UrlGroup _urlGroup;
|
private readonly UrlGroup _urlGroup;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
@ -54,13 +55,13 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
// Set the association between request queue and url group. After this, requests for registered urls will
|
// Set the association between request queue and url group. After this, requests for registered urls will
|
||||||
// get delivered to this request queue.
|
// get delivered to this request queue.
|
||||||
|
|
||||||
var info = new HttpApi.HTTP_BINDING_INFO();
|
var info = new HttpApiTypes.HTTP_BINDING_INFO();
|
||||||
info.Flags = HttpApi.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT;
|
info.Flags = HttpApiTypes.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT;
|
||||||
info.RequestQueueHandle = Handle.DangerousGetHandle();
|
info.RequestQueueHandle = Handle.DangerousGetHandle();
|
||||||
|
|
||||||
var infoptr = new IntPtr(&info);
|
var infoptr = new IntPtr(&info);
|
||||||
|
|
||||||
_urlGroup.SetProperty(HttpApi.HTTP_SERVER_PROPERTY.HttpServerBindingProperty,
|
_urlGroup.SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerBindingProperty,
|
||||||
infoptr, (uint)BindingInfoSize);
|
infoptr, (uint)BindingInfoSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,13 +74,13 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
// is fine since http.sys allows to set HttpServerBindingProperty multiple times for valid
|
// is fine since http.sys allows to set HttpServerBindingProperty multiple times for valid
|
||||||
// Url groups.
|
// Url groups.
|
||||||
|
|
||||||
var info = new HttpApi.HTTP_BINDING_INFO();
|
var info = new HttpApiTypes.HTTP_BINDING_INFO();
|
||||||
info.Flags = HttpApi.HTTP_FLAGS.NONE;
|
info.Flags = HttpApiTypes.HTTP_FLAGS.NONE;
|
||||||
info.RequestQueueHandle = IntPtr.Zero;
|
info.RequestQueueHandle = IntPtr.Zero;
|
||||||
|
|
||||||
var infoptr = new IntPtr(&info);
|
var infoptr = new IntPtr(&info);
|
||||||
|
|
||||||
_urlGroup.SetProperty(HttpApi.HTTP_SERVER_PROPERTY.HttpServerBindingProperty,
|
_urlGroup.SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerBindingProperty,
|
||||||
infoptr, (uint)BindingInfoSize, throwOnError: false);
|
infoptr, (uint)BindingInfoSize, throwOnError: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,7 +90,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
CheckDisposed();
|
CheckDisposed();
|
||||||
|
|
||||||
var result = HttpApi.HttpSetRequestQueueProperty(Handle,
|
var result = HttpApi.HttpSetRequestQueueProperty(Handle,
|
||||||
HttpApi.HTTP_SERVER_PROPERTY.HttpServerQueueLengthProperty,
|
HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerQueueLengthProperty,
|
||||||
new IntPtr((void*)&length), (uint)Marshal.SizeOf<long>(), 0, IntPtr.Zero);
|
new IntPtr((void*)&length), (uint)Marshal.SizeOf<long>(), 0, IntPtr.Zero);
|
||||||
|
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using static Microsoft.AspNetCore.Server.HttpSys.HttpApi;
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using static Microsoft.AspNetCore.Server.HttpSys.UnsafeNclNativeMethods.TokenBinding;
|
using static Microsoft.AspNetCore.HttpSys.Internal.HttpApiTypes;
|
||||||
|
using static Microsoft.AspNetCore.HttpSys.Internal.UnsafeNclNativeMethods.TokenBinding;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
@ -11,7 +12,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
internal class UrlGroup : IDisposable
|
internal class UrlGroup : IDisposable
|
||||||
{
|
{
|
||||||
private static readonly int QosInfoSize =
|
private static readonly int QosInfoSize =
|
||||||
Marshal.SizeOf<HttpApi.HTTP_QOS_SETTING_INFO>();
|
Marshal.SizeOf<HttpApiTypes.HTTP_QOS_SETTING_INFO>();
|
||||||
|
|
||||||
private ServerSession _serverSession;
|
private ServerSession _serverSession;
|
||||||
private ILogger _logger;
|
private ILogger _logger;
|
||||||
|
|
@ -39,18 +40,18 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
||||||
internal unsafe void SetMaxConnections(long maxConnections)
|
internal unsafe void SetMaxConnections(long maxConnections)
|
||||||
{
|
{
|
||||||
var connectionLimit = new HttpApi.HTTP_CONNECTION_LIMIT_INFO();
|
var connectionLimit = new HttpApiTypes.HTTP_CONNECTION_LIMIT_INFO();
|
||||||
connectionLimit.Flags = HttpApi.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT;
|
connectionLimit.Flags = HttpApiTypes.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT;
|
||||||
connectionLimit.MaxConnections = (uint)maxConnections;
|
connectionLimit.MaxConnections = (uint)maxConnections;
|
||||||
|
|
||||||
var qosSettings = new HttpApi.HTTP_QOS_SETTING_INFO();
|
var qosSettings = new HttpApiTypes.HTTP_QOS_SETTING_INFO();
|
||||||
qosSettings.QosType = HttpApi.HTTP_QOS_SETTING_TYPE.HttpQosSettingTypeConnectionLimit;
|
qosSettings.QosType = HttpApiTypes.HTTP_QOS_SETTING_TYPE.HttpQosSettingTypeConnectionLimit;
|
||||||
qosSettings.QosSetting = new IntPtr(&connectionLimit);
|
qosSettings.QosSetting = new IntPtr(&connectionLimit);
|
||||||
|
|
||||||
SetProperty(HttpApi.HTTP_SERVER_PROPERTY.HttpServerQosProperty, new IntPtr(&qosSettings), (uint)QosInfoSize);
|
SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerQosProperty, new IntPtr(&qosSettings), (uint)QosInfoSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SetProperty(HttpApi.HTTP_SERVER_PROPERTY property, IntPtr info, uint infosize, bool throwOnError = true)
|
internal void SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY property, IntPtr info, uint infosize, bool throwOnError = true)
|
||||||
{
|
{
|
||||||
Debug.Assert(info != IntPtr.Zero, "SetUrlGroupProperty called with invalid pointer");
|
Debug.Assert(info != IntPtr.Zero, "SetUrlGroupProperty called with invalid pointer");
|
||||||
CheckDisposed();
|
CheckDisposed();
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ using System.Security.Cryptography;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
@ -23,11 +24,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
private const uint CertBoblSize = 1500;
|
private const uint CertBoblSize = 1500;
|
||||||
private static readonly IOCompletionCallback IOCallback = new IOCompletionCallback(WaitCallback);
|
private static readonly IOCompletionCallback IOCallback = new IOCompletionCallback(WaitCallback);
|
||||||
private static readonly int RequestChannelBindStatusSize =
|
private static readonly int RequestChannelBindStatusSize =
|
||||||
Marshal.SizeOf<HttpApi.HTTP_REQUEST_CHANNEL_BIND_STATUS>();
|
Marshal.SizeOf<HttpApiTypes.HTTP_REQUEST_CHANNEL_BIND_STATUS>();
|
||||||
|
|
||||||
private SafeNativeOverlapped _overlapped;
|
private SafeNativeOverlapped _overlapped;
|
||||||
private byte[] _backingBuffer;
|
private byte[] _backingBuffer;
|
||||||
private HttpApi.HTTP_SSL_CLIENT_CERT_INFO* _memoryBlob;
|
private HttpApiTypes.HTTP_SSL_CLIENT_CERT_INFO* _memoryBlob;
|
||||||
private uint _size;
|
private uint _size;
|
||||||
private TaskCompletionSource<object> _tcs;
|
private TaskCompletionSource<object> _tcs;
|
||||||
private RequestContext _requestContext;
|
private RequestContext _requestContext;
|
||||||
|
|
@ -104,7 +105,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpApi.HTTP_SSL_CLIENT_CERT_INFO* RequestBlob
|
private HttpApiTypes.HTTP_SSL_CLIENT_CERT_INFO* RequestBlob
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
@ -134,7 +135,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
var boundHandle = RequestContext.Server.RequestQueue.BoundHandle;
|
var boundHandle = RequestContext.Server.RequestQueue.BoundHandle;
|
||||||
_overlapped = new SafeNativeOverlapped(boundHandle,
|
_overlapped = new SafeNativeOverlapped(boundHandle,
|
||||||
boundHandle.AllocateNativeOverlapped(IOCallback, this, _backingBuffer));
|
boundHandle.AllocateNativeOverlapped(IOCallback, this, _backingBuffer));
|
||||||
_memoryBlob = (HttpApi.HTTP_SSL_CLIENT_CERT_INFO*)Marshal.UnsafeAddrOfPinnedArrayElement(_backingBuffer, 0);
|
_memoryBlob = (HttpApiTypes.HTTP_SSL_CLIENT_CERT_INFO*)Marshal.UnsafeAddrOfPinnedArrayElement(_backingBuffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// When you use netsh to configure HTTP.SYS with clientcertnegotiation = enable
|
// When you use netsh to configure HTTP.SYS with clientcertnegotiation = enable
|
||||||
|
|
@ -168,7 +169,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
HttpApi.HttpReceiveClientCertificate(
|
HttpApi.HttpReceiveClientCertificate(
|
||||||
RequestQueueHandle,
|
RequestQueueHandle,
|
||||||
RequestContext.Request.UConnectionId,
|
RequestContext.Request.UConnectionId,
|
||||||
(uint)HttpApi.HTTP_FLAGS.NONE,
|
(uint)HttpApiTypes.HTTP_FLAGS.NONE,
|
||||||
RequestBlob,
|
RequestBlob,
|
||||||
size,
|
size,
|
||||||
&bytesReceived,
|
&bytesReceived,
|
||||||
|
|
@ -176,7 +177,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
||||||
if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA)
|
if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA)
|
||||||
{
|
{
|
||||||
HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = RequestBlob;
|
HttpApiTypes.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = RequestBlob;
|
||||||
size = bytesReceived + pClientCertInfo->CertEncodedSize;
|
size = bytesReceived + pClientCertInfo->CertEncodedSize;
|
||||||
Reset(size);
|
Reset(size);
|
||||||
retry = true;
|
retry = true;
|
||||||
|
|
@ -239,7 +240,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
// return the size of the initial cert structure. To get the full size,
|
// return the size of the initial cert structure. To get the full size,
|
||||||
// we need to add the certificate encoding size as well.
|
// we need to add the certificate encoding size as well.
|
||||||
|
|
||||||
HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = asyncResult.RequestBlob;
|
HttpApiTypes.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = asyncResult.RequestBlob;
|
||||||
asyncResult.Reset(numBytes + pClientCertInfo->CertEncodedSize);
|
asyncResult.Reset(numBytes + pClientCertInfo->CertEncodedSize);
|
||||||
|
|
||||||
uint bytesReceived = 0;
|
uint bytesReceived = 0;
|
||||||
|
|
@ -247,7 +248,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
HttpApi.HttpReceiveClientCertificate(
|
HttpApi.HttpReceiveClientCertificate(
|
||||||
requestContext.Server.RequestQueue.Handle,
|
requestContext.Server.RequestQueue.Handle,
|
||||||
requestContext.Request.UConnectionId,
|
requestContext.Request.UConnectionId,
|
||||||
(uint)HttpApi.HTTP_FLAGS.NONE,
|
(uint)HttpApiTypes.HTTP_FLAGS.NONE,
|
||||||
asyncResult._memoryBlob,
|
asyncResult._memoryBlob,
|
||||||
asyncResult._size,
|
asyncResult._size,
|
||||||
&bytesReceived,
|
&bytesReceived,
|
||||||
|
|
@ -271,7 +272,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HttpApi.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = asyncResult._memoryBlob;
|
HttpApiTypes.HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo = asyncResult._memoryBlob;
|
||||||
if (pClientCertInfo == null)
|
if (pClientCertInfo == null)
|
||||||
{
|
{
|
||||||
asyncResult.Complete(0, null);
|
asyncResult.Complete(0, null);
|
||||||
|
|
@ -374,7 +375,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
statusCode = HttpApi.HttpReceiveClientCertificate(
|
statusCode = HttpApi.HttpReceiveClientCertificate(
|
||||||
requestQueue.Handle,
|
requestQueue.Handle,
|
||||||
connectionId,
|
connectionId,
|
||||||
(uint)HttpApi.HTTP_FLAGS.HTTP_RECEIVE_SECURE_CHANNEL_TOKEN,
|
(uint)HttpApiTypes.HTTP_FLAGS.HTTP_RECEIVE_SECURE_CHANNEL_TOKEN,
|
||||||
blobPtr,
|
blobPtr,
|
||||||
(uint)size,
|
(uint)size,
|
||||||
&bytesReceived,
|
&bytesReceived,
|
||||||
|
|
@ -418,7 +419,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
private static int GetTokenOffsetFromBlob(IntPtr blob)
|
private static int GetTokenOffsetFromBlob(IntPtr blob)
|
||||||
{
|
{
|
||||||
Debug.Assert(blob != IntPtr.Zero);
|
Debug.Assert(blob != IntPtr.Zero);
|
||||||
IntPtr tokenPointer = Marshal.ReadIntPtr(blob, (int)Marshal.OffsetOf<HttpApi.HTTP_REQUEST_CHANNEL_BIND_STATUS>("ChannelToken"));
|
IntPtr tokenPointer = Marshal.ReadIntPtr(blob, (int)Marshal.OffsetOf<HttpApiTypes.HTTP_REQUEST_CHANNEL_BIND_STATUS>("ChannelToken"));
|
||||||
Debug.Assert(tokenPointer != IntPtr.Zero);
|
Debug.Assert(tokenPointer != IntPtr.Zero);
|
||||||
return (int)IntPtrHelper.Subtract(tokenPointer, blob);
|
return (int)IntPtrHelper.Subtract(tokenPointer, blob);
|
||||||
}
|
}
|
||||||
|
|
@ -426,7 +427,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
private static int GetTokenSizeFromBlob(IntPtr blob)
|
private static int GetTokenSizeFromBlob(IntPtr blob)
|
||||||
{
|
{
|
||||||
Debug.Assert(blob != IntPtr.Zero);
|
Debug.Assert(blob != IntPtr.Zero);
|
||||||
return Marshal.ReadInt32(blob, (int)Marshal.OffsetOf<HttpApi.HTTP_REQUEST_CHANNEL_BIND_STATUS>("ChannelTokenSize"));
|
return Marshal.ReadInt32(blob, (int)Marshal.OffsetOf<HttpApiTypes.HTTP_REQUEST_CHANNEL_BIND_STATUS>("ChannelTokenSize"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,434 +0,0 @@
|
||||||
// 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;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Security.Principal;
|
|
||||||
using Microsoft.Extensions.Primitives;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
|
||||||
{
|
|
||||||
internal unsafe class NativeRequestContext : IDisposable
|
|
||||||
{
|
|
||||||
private const int DefaultBufferSize = 4096;
|
|
||||||
private const int AlignmentPadding = 8;
|
|
||||||
private HttpApi.HTTP_REQUEST* _nativeRequest;
|
|
||||||
private IntPtr _originalBufferAddress;
|
|
||||||
private byte[] _backingBuffer;
|
|
||||||
private int _bufferAlignment;
|
|
||||||
private SafeNativeOverlapped _nativeOverlapped;
|
|
||||||
private AsyncAcceptContext _acceptResult;
|
|
||||||
|
|
||||||
internal NativeRequestContext(AsyncAcceptContext result)
|
|
||||||
{
|
|
||||||
_acceptResult = result;
|
|
||||||
AllocateNativeRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal SafeNativeOverlapped NativeOverlapped => _nativeOverlapped;
|
|
||||||
|
|
||||||
internal HttpApi.HTTP_REQUEST* NativeRequest
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Debug.Assert(_nativeRequest != null || _backingBuffer == null, "native request accessed after ReleasePins().");
|
|
||||||
return _nativeRequest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private HttpApi.HTTP_REQUEST_V2* NativeRequestV2
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Debug.Assert(_nativeRequest != null || _backingBuffer == null, "native request accessed after ReleasePins().");
|
|
||||||
return (HttpApi.HTTP_REQUEST_V2*)_nativeRequest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal ulong RequestId
|
|
||||||
{
|
|
||||||
get { return NativeRequest->RequestId; }
|
|
||||||
set { NativeRequest->RequestId = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
internal ulong ConnectionId => NativeRequest->ConnectionId;
|
|
||||||
|
|
||||||
internal HttpApi.HTTP_VERB VerbId => NativeRequest->Verb;
|
|
||||||
|
|
||||||
internal ulong UrlContext => NativeRequest->UrlContext;
|
|
||||||
|
|
||||||
internal ushort UnknownHeaderCount => NativeRequest->Headers.UnknownHeaderCount;
|
|
||||||
|
|
||||||
internal SslStatus SslStatus
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return NativeRequest->pSslInfo == null ? SslStatus.Insecure :
|
|
||||||
NativeRequest->pSslInfo->SslClientCertNegotiated == 0 ? SslStatus.NoClientCert :
|
|
||||||
SslStatus.ClientCert;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal uint Size
|
|
||||||
{
|
|
||||||
get { return (uint)_backingBuffer.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.");
|
|
||||||
_originalBufferAddress = (IntPtr)_nativeRequest;
|
|
||||||
_nativeRequest = null;
|
|
||||||
_nativeOverlapped?.Dispose();
|
|
||||||
_nativeOverlapped = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Debug.Assert(_nativeRequest == null, "RequestContextBase::Dispose()|Dispose() called before ReleasePins().");
|
|
||||||
_nativeOverlapped?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetBuffer(int size)
|
|
||||||
{
|
|
||||||
Debug.Assert(size != 0, "unexpected size");
|
|
||||||
|
|
||||||
_backingBuffer = new byte[size + AlignmentPadding];
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AllocateNativeRequest(uint? size = null)
|
|
||||||
{
|
|
||||||
// We can't reuse overlapped objects
|
|
||||||
_nativeOverlapped?.Dispose();
|
|
||||||
|
|
||||||
uint newSize = size.HasValue ? size.Value : _backingBuffer == null ? DefaultBufferSize : Size;
|
|
||||||
SetBuffer(checked((int)newSize));
|
|
||||||
var boundHandle = _acceptResult.Server.RequestQueue.BoundHandle;
|
|
||||||
_nativeOverlapped = new SafeNativeOverlapped(boundHandle,
|
|
||||||
boundHandle.AllocateNativeOverlapped(AsyncAcceptContext.IOCallback, _acceptResult, _backingBuffer));
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
_bufferAlignment = 0;
|
|
||||||
|
|
||||||
_nativeRequest = (HttpApi.HTTP_REQUEST*)(requestAddress + _bufferAlignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Reset(ulong requestId = 0, uint? size = null)
|
|
||||||
{
|
|
||||||
Debug.Assert(_nativeRequest != null || _backingBuffer == null, "RequestContextBase::Dispose()|SetNativeRequest() called after ReleasePins().");
|
|
||||||
AllocateNativeRequest(size);
|
|
||||||
RequestId = requestId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These methods require the HTTP_REQUEST to still be pinned in its original location.
|
|
||||||
|
|
||||||
internal string GetVerb()
|
|
||||||
{
|
|
||||||
var verb = NativeRequest->Verb;
|
|
||||||
if (verb > HttpApi.HTTP_VERB.HttpVerbUnknown && verb < HttpApi.HTTP_VERB.HttpVerbMaximum)
|
|
||||||
{
|
|
||||||
return HttpApi.HttpVerbs[(int)verb];
|
|
||||||
}
|
|
||||||
else if (verb == HttpApi.HTTP_VERB.HttpVerbUnknown && NativeRequest->pUnknownVerb != null)
|
|
||||||
{
|
|
||||||
return HeaderEncoding.GetString(NativeRequest->pUnknownVerb, NativeRequest->UnknownVerbLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal string GetRawUrl()
|
|
||||||
{
|
|
||||||
if (NativeRequest->pRawUrl != null && NativeRequest->RawUrlLength > 0)
|
|
||||||
{
|
|
||||||
return Marshal.PtrToStringAnsi((IntPtr)NativeRequest->pRawUrl, NativeRequest->RawUrlLength);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal byte[] GetRawUrlInBytes()
|
|
||||||
{
|
|
||||||
if (NativeRequest->pRawUrl != null && NativeRequest->RawUrlLength > 0)
|
|
||||||
{
|
|
||||||
var result = new byte[NativeRequest->RawUrlLength];
|
|
||||||
Marshal.Copy((IntPtr)NativeRequest->pRawUrl, result, 0, NativeRequest->RawUrlLength);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal CookedUrl GetCookedUrl()
|
|
||||||
{
|
|
||||||
return new CookedUrl(NativeRequest->CookedUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Version GetVersion()
|
|
||||||
{
|
|
||||||
var major = NativeRequest->Version.MajorVersion;
|
|
||||||
var minor = NativeRequest->Version.MinorVersion;
|
|
||||||
if (major == 1 && minor == 1)
|
|
||||||
{
|
|
||||||
return Constants.V1_1;
|
|
||||||
}
|
|
||||||
else if (major == 1 && minor == 0)
|
|
||||||
{
|
|
||||||
return Constants.V1_0;
|
|
||||||
}
|
|
||||||
return new Version(major, minor);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal bool CheckAuthenticated()
|
|
||||||
{
|
|
||||||
var requestInfo = NativeRequestV2->pRequestInfo;
|
|
||||||
var infoCount = NativeRequestV2->RequestInfoCount;
|
|
||||||
|
|
||||||
for (int i = 0; i < infoCount; i++)
|
|
||||||
{
|
|
||||||
var info = &requestInfo[i];
|
|
||||||
if (info != null
|
|
||||||
&& info->InfoType == HttpApi.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeAuth
|
|
||||||
&& info->pInfo->AuthStatus == HttpApi.HTTP_AUTH_STATUS.HttpAuthStatusSuccess)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal WindowsPrincipal GetUser()
|
|
||||||
{
|
|
||||||
var requestInfo = NativeRequestV2->pRequestInfo;
|
|
||||||
var infoCount = NativeRequestV2->RequestInfoCount;
|
|
||||||
|
|
||||||
for (int i = 0; i < infoCount; i++)
|
|
||||||
{
|
|
||||||
var info = &requestInfo[i];
|
|
||||||
if (info != null
|
|
||||||
&& info->InfoType == HttpApi.HTTP_REQUEST_INFO_TYPE.HttpRequestInfoTypeAuth
|
|
||||||
&& info->pInfo->AuthStatus == HttpApi.HTTP_AUTH_STATUS.HttpAuthStatusSuccess)
|
|
||||||
{
|
|
||||||
// Duplicates AccessToken
|
|
||||||
var identity = new WindowsIdentity(info->pInfo->AccessToken,
|
|
||||||
GetAuthTypeFromRequest(info->pInfo->AuthType).ToString());
|
|
||||||
|
|
||||||
// Close the original
|
|
||||||
UnsafeNclNativeMethods.SafeNetHandles.CloseHandle(info->pInfo->AccessToken);
|
|
||||||
|
|
||||||
return new WindowsPrincipal(identity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new WindowsPrincipal(WindowsIdentity.GetAnonymous()); // Anonymous / !IsAuthenticated
|
|
||||||
}
|
|
||||||
|
|
||||||
private static AuthenticationSchemes GetAuthTypeFromRequest(HttpApi.HTTP_REQUEST_AUTH_TYPE input)
|
|
||||||
{
|
|
||||||
switch (input)
|
|
||||||
{
|
|
||||||
case HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeBasic:
|
|
||||||
return AuthenticationSchemes.Basic;
|
|
||||||
// case HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeDigest:
|
|
||||||
// return AuthenticationSchemes.Digest;
|
|
||||||
case HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeNTLM:
|
|
||||||
return AuthenticationSchemes.NTLM;
|
|
||||||
case HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeNegotiate:
|
|
||||||
return AuthenticationSchemes.Negotiate;
|
|
||||||
case HttpApi.HTTP_REQUEST_AUTH_TYPE.HttpRequestAuthTypeKerberos:
|
|
||||||
return AuthenticationSchemes.Kerberos;
|
|
||||||
default:
|
|
||||||
throw new NotImplementedException(input.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// These methods are for accessing the request structure after it has been unpinned. They need to adjust addresses
|
|
||||||
// in case GC has moved the original object.
|
|
||||||
|
|
||||||
internal string GetKnownHeader(HttpSysRequestHeader header)
|
|
||||||
{
|
|
||||||
fixed (byte* pMemoryBlob = _backingBuffer)
|
|
||||||
{
|
|
||||||
var request = (HttpApi.HTTP_REQUEST*)(pMemoryBlob + _bufferAlignment);
|
|
||||||
long fixup = pMemoryBlob - (byte*)_originalBufferAddress;
|
|
||||||
int headerIndex = (int)header;
|
|
||||||
string value = null;
|
|
||||||
|
|
||||||
HttpApi.HTTP_KNOWN_HEADER* pKnownHeader = (&request->Headers.KnownHeaders) + headerIndex;
|
|
||||||
// For known headers, when header value is empty, RawValueLength will be 0 and
|
|
||||||
// pRawValue will point to empty string ("\0")
|
|
||||||
if (pKnownHeader->pRawValue != null)
|
|
||||||
{
|
|
||||||
value = HeaderEncoding.GetString(pKnownHeader->pRawValue + fixup, pKnownHeader->RawValueLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void GetUnknownHeaders(IDictionary<string, StringValues> unknownHeaders)
|
|
||||||
{
|
|
||||||
// Return value.
|
|
||||||
fixed (byte* pMemoryBlob = _backingBuffer)
|
|
||||||
{
|
|
||||||
var request = (HttpApi.HTTP_REQUEST*)(pMemoryBlob + _bufferAlignment);
|
|
||||||
long fixup = pMemoryBlob - (byte*)_originalBufferAddress;
|
|
||||||
int index;
|
|
||||||
|
|
||||||
// unknown headers
|
|
||||||
if (request->Headers.UnknownHeaderCount != 0)
|
|
||||||
{
|
|
||||||
var pUnknownHeader = (HttpApi.HTTP_UNKNOWN_HEADER*)(fixup + (byte*)request->Headers.pUnknownHeaders);
|
|
||||||
for (index = 0; index < request->Headers.UnknownHeaderCount; index++)
|
|
||||||
{
|
|
||||||
// For unknown headers, when header value is empty, RawValueLength will be 0 and
|
|
||||||
// pRawValue will be null.
|
|
||||||
if (pUnknownHeader->pName != null && pUnknownHeader->NameLength > 0)
|
|
||||||
{
|
|
||||||
var headerName = HeaderEncoding.GetString(pUnknownHeader->pName + fixup, pUnknownHeader->NameLength);
|
|
||||||
string headerValue;
|
|
||||||
if (pUnknownHeader->pRawValue != null && pUnknownHeader->RawValueLength > 0)
|
|
||||||
{
|
|
||||||
headerValue = HeaderEncoding.GetString(pUnknownHeader->pRawValue + fixup, pUnknownHeader->RawValueLength);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
headerValue = string.Empty;
|
|
||||||
}
|
|
||||||
// Note that Http.Sys currently collapses all headers of the same name to a single coma separated string,
|
|
||||||
// so we can just call Set.
|
|
||||||
unknownHeaders[headerName] = headerValue;
|
|
||||||
}
|
|
||||||
pUnknownHeader++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal SocketAddress GetRemoteEndPoint()
|
|
||||||
{
|
|
||||||
return GetEndPoint(localEndpoint: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal SocketAddress GetLocalEndPoint()
|
|
||||||
{
|
|
||||||
return GetEndPoint(localEndpoint: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SocketAddress GetEndPoint(bool localEndpoint)
|
|
||||||
{
|
|
||||||
fixed (byte* pMemoryBlob = _backingBuffer)
|
|
||||||
{
|
|
||||||
var request = (HttpApi.HTTP_REQUEST*)(pMemoryBlob + _bufferAlignment);
|
|
||||||
var source = localEndpoint ? (byte*)request->Address.pLocalAddress : (byte*)request->Address.pRemoteAddress;
|
|
||||||
|
|
||||||
if (source == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
var address = (IntPtr)(pMemoryBlob + _bufferAlignment - (byte*)_originalBufferAddress + source);
|
|
||||||
return CopyOutAddress(address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static SocketAddress CopyOutAddress(IntPtr address)
|
|
||||||
{
|
|
||||||
ushort addressFamily = *((ushort*)address);
|
|
||||||
if (addressFamily == (ushort)AddressFamily.InterNetwork)
|
|
||||||
{
|
|
||||||
var v4address = new SocketAddress(AddressFamily.InterNetwork, SocketAddress.IPv4AddressSize);
|
|
||||||
fixed (byte* pBuffer = v4address.Buffer)
|
|
||||||
{
|
|
||||||
for (int index = 2; index < SocketAddress.IPv4AddressSize; index++)
|
|
||||||
{
|
|
||||||
pBuffer[index] = ((byte*)address)[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return v4address;
|
|
||||||
}
|
|
||||||
if (addressFamily == (ushort)AddressFamily.InterNetworkV6)
|
|
||||||
{
|
|
||||||
var v6address = new SocketAddress(AddressFamily.InterNetworkV6, SocketAddress.IPv6AddressSize);
|
|
||||||
fixed (byte* pBuffer = v6address.Buffer)
|
|
||||||
{
|
|
||||||
for (int index = 2; index < SocketAddress.IPv6AddressSize; index++)
|
|
||||||
{
|
|
||||||
pBuffer[index] = ((byte*)address)[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return v6address;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal uint GetChunks(ref int dataChunkIndex, ref uint dataChunkOffset, byte[] buffer, int offset, int size)
|
|
||||||
{
|
|
||||||
// Return value.
|
|
||||||
uint dataRead = 0;
|
|
||||||
fixed (byte* pMemoryBlob = _backingBuffer)
|
|
||||||
{
|
|
||||||
var request = (HttpApi.HTTP_REQUEST*)(pMemoryBlob + _bufferAlignment);
|
|
||||||
long fixup = pMemoryBlob - (byte*)_originalBufferAddress;
|
|
||||||
|
|
||||||
if (request->EntityChunkCount > 0 && dataChunkIndex < request->EntityChunkCount && dataChunkIndex != -1)
|
|
||||||
{
|
|
||||||
var pDataChunk = (HttpApi.HTTP_DATA_CHUNK*)(fixup + (byte*)&request->pEntityChunks[dataChunkIndex]);
|
|
||||||
|
|
||||||
fixed (byte* pReadBuffer = buffer)
|
|
||||||
{
|
|
||||||
byte* pTo = &pReadBuffer[offset];
|
|
||||||
|
|
||||||
while (dataChunkIndex < request->EntityChunkCount && dataRead < size)
|
|
||||||
{
|
|
||||||
if (dataChunkOffset >= pDataChunk->fromMemory.BufferLength)
|
|
||||||
{
|
|
||||||
dataChunkOffset = 0;
|
|
||||||
dataChunkIndex++;
|
|
||||||
pDataChunk++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
byte* pFrom = (byte*)pDataChunk->fromMemory.pBuffer + dataChunkOffset + fixup;
|
|
||||||
|
|
||||||
uint bytesToRead = pDataChunk->fromMemory.BufferLength - (uint)dataChunkOffset;
|
|
||||||
if (bytesToRead > (uint)size)
|
|
||||||
{
|
|
||||||
bytesToRead = (uint)size;
|
|
||||||
}
|
|
||||||
for (uint i = 0; i < bytesToRead; i++)
|
|
||||||
{
|
|
||||||
*(pTo++) = *(pFrom++);
|
|
||||||
}
|
|
||||||
dataRead += bytesToRead;
|
|
||||||
dataChunkOffset += bytesToRead;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// we're finished.
|
|
||||||
if (dataChunkIndex == request->EntityChunkCount)
|
|
||||||
{
|
|
||||||
dataChunkIndex = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dataRead;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,11 +5,11 @@ using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
|
|
@ -27,8 +27,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
private long? _contentLength;
|
private long? _contentLength;
|
||||||
private RequestStream _nativeStream;
|
private RequestStream _nativeStream;
|
||||||
|
|
||||||
private SocketAddress _localEndPoint;
|
private AspNetCore.HttpSys.Internal.SocketAddress _localEndPoint;
|
||||||
private SocketAddress _remoteEndPoint;
|
private AspNetCore.HttpSys.Internal.SocketAddress _remoteEndPoint;
|
||||||
|
|
||||||
private bool _isDisposed = false;
|
private bool _isDisposed = false;
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
var originalPath = RequestUriBuilder.DecodeAndUnescapePath(rawUrlInBytes);
|
var originalPath = RequestUriBuilder.DecodeAndUnescapePath(rawUrlInBytes);
|
||||||
|
|
||||||
// 'OPTIONS * HTTP/1.1'
|
// 'OPTIONS * HTTP/1.1'
|
||||||
if (KnownMethod == HttpApi.HTTP_VERB.HttpVerbOPTIONS && string.Equals(RawUrl, "*", StringComparison.Ordinal))
|
if (KnownMethod == HttpApiTypes.HTTP_VERB.HttpVerbOPTIONS && string.Equals(RawUrl, "*", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
PathBase = string.Empty;
|
PathBase = string.Empty;
|
||||||
Path = string.Empty;
|
Path = string.Empty;
|
||||||
|
|
@ -79,9 +79,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
||||||
ProtocolVersion = _nativeRequestContext.GetVersion();
|
ProtocolVersion = _nativeRequestContext.GetVersion();
|
||||||
|
|
||||||
Headers = new HeaderCollection(new RequestHeaders(_nativeRequestContext));
|
Headers = new RequestHeaders(_nativeRequestContext);
|
||||||
|
|
||||||
User = nativeRequestContext.GetUser();
|
User = _nativeRequestContext.GetUser();
|
||||||
|
|
||||||
// GetTlsTokenBindingInfo(); TODO: https://github.com/aspnet/HttpSysServer/issues/231
|
// GetTlsTokenBindingInfo(); TODO: https://github.com/aspnet/HttpSysServer/issues/231
|
||||||
|
|
||||||
|
|
@ -136,11 +136,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public HeaderCollection Headers { get; }
|
public RequestHeaders Headers { get; }
|
||||||
|
|
||||||
internal HttpApi.HTTP_VERB KnownMethod { get; }
|
internal HttpApiTypes.HTTP_VERB KnownMethod { get; }
|
||||||
|
|
||||||
internal bool IsHeadMethod => KnownMethod == HttpApi.HTTP_VERB.HttpVerbHEAD;
|
internal bool IsHeadMethod => KnownMethod == HttpApiTypes.HTTP_VERB.HttpVerbHEAD;
|
||||||
|
|
||||||
public string Method { get; }
|
public string Method { get; }
|
||||||
|
|
||||||
|
|
@ -190,7 +190,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SocketAddress RemoteEndPoint
|
private AspNetCore.HttpSys.Internal.SocketAddress RemoteEndPoint
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
@ -203,7 +203,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SocketAddress LocalEndPoint
|
private AspNetCore.HttpSys.Internal.SocketAddress LocalEndPoint
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ using System.Security.Principal;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,9 @@ using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
using static Microsoft.AspNetCore.Server.HttpSys.UnsafeNclNativeMethods;
|
using static Microsoft.AspNetCore.HttpSys.Internal.UnsafeNclNativeMethods;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
|
|
@ -24,7 +25,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
private TimeSpan? _cacheTtl;
|
private TimeSpan? _cacheTtl;
|
||||||
private long _expectedBodyLength;
|
private long _expectedBodyLength;
|
||||||
private BoundaryType _boundaryType;
|
private BoundaryType _boundaryType;
|
||||||
private HttpApi.HTTP_RESPONSE_V2 _nativeResponse;
|
private HttpApiTypes.HTTP_RESPONSE_V2 _nativeResponse;
|
||||||
|
|
||||||
internal Response(RequestContext requestContext)
|
internal Response(RequestContext requestContext)
|
||||||
{
|
{
|
||||||
|
|
@ -33,7 +34,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
Headers = new HeaderCollection();
|
Headers = new HeaderCollection();
|
||||||
// We haven't started yet, or we're just buffered, we can clear any data, headers, and state so
|
// We haven't started yet, or we're just buffered, we can clear any data, headers, and state so
|
||||||
// that we can start over (e.g. to write an error message).
|
// that we can start over (e.g. to write an error message).
|
||||||
_nativeResponse = new HttpApi.HTTP_RESPONSE_V2();
|
_nativeResponse = new HttpApiTypes.HTTP_RESPONSE_V2();
|
||||||
Headers.IsReadOnly = false;
|
Headers.IsReadOnly = false;
|
||||||
Headers.Clear();
|
Headers.Clear();
|
||||||
_reasonPhrase = null;
|
_reasonPhrase = null;
|
||||||
|
|
@ -249,9 +250,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
// What would we loose by bypassing HttpSendHttpResponse?
|
// What would we loose by bypassing HttpSendHttpResponse?
|
||||||
//
|
//
|
||||||
// TODO: Consider using the HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA flag for most/all responses rather than just Opaque.
|
// TODO: Consider using the HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA flag for most/all responses rather than just Opaque.
|
||||||
internal unsafe uint SendHeaders(HttpApi.HTTP_DATA_CHUNK[] dataChunks,
|
internal unsafe uint SendHeaders(HttpApiTypes.HTTP_DATA_CHUNK[] dataChunks,
|
||||||
ResponseStreamAsyncResult asyncResult,
|
ResponseStreamAsyncResult asyncResult,
|
||||||
HttpApi.HTTP_FLAGS flags,
|
HttpApiTypes.HTTP_FLAGS flags,
|
||||||
bool isOpaqueUpgrade)
|
bool isOpaqueUpgrade)
|
||||||
{
|
{
|
||||||
Debug.Assert(!HasStarted, "HttpListenerResponse::SendHeaders()|SentHeaders is true.");
|
Debug.Assert(!HasStarted, "HttpListenerResponse::SendHeaders()|SentHeaders is true.");
|
||||||
|
|
@ -273,7 +274,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
var handle = GCHandle.Alloc(dataChunks, GCHandleType.Pinned);
|
var handle = GCHandle.Alloc(dataChunks, GCHandleType.Pinned);
|
||||||
pinnedHeaders.Add(handle);
|
pinnedHeaders.Add(handle);
|
||||||
_nativeResponse.Response_V1.EntityChunkCount = (ushort)dataChunks.Length;
|
_nativeResponse.Response_V1.EntityChunkCount = (ushort)dataChunks.Length;
|
||||||
_nativeResponse.Response_V1.pEntityChunks = (HttpApi.HTTP_DATA_CHUNK*)handle.AddrOfPinnedObject();
|
_nativeResponse.Response_V1.pEntityChunks = (HttpApiTypes.HTTP_DATA_CHUNK*)handle.AddrOfPinnedObject();
|
||||||
}
|
}
|
||||||
else if (asyncResult != null && asyncResult.DataChunks != null)
|
else if (asyncResult != null && asyncResult.DataChunks != null)
|
||||||
{
|
{
|
||||||
|
|
@ -286,10 +287,10 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
_nativeResponse.Response_V1.pEntityChunks = null;
|
_nativeResponse.Response_V1.pEntityChunks = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var cachePolicy = new HttpApi.HTTP_CACHE_POLICY();
|
var cachePolicy = new HttpApiTypes.HTTP_CACHE_POLICY();
|
||||||
if (_cacheTtl.HasValue && _cacheTtl.Value > TimeSpan.Zero)
|
if (_cacheTtl.HasValue && _cacheTtl.Value > TimeSpan.Zero)
|
||||||
{
|
{
|
||||||
cachePolicy.Policy = HttpApi.HTTP_CACHE_POLICY_TYPE.HttpCachePolicyTimeToLive;
|
cachePolicy.Policy = HttpApiTypes.HTTP_CACHE_POLICY_TYPE.HttpCachePolicyTimeToLive;
|
||||||
cachePolicy.SecondsToLive = (uint)Math.Min(_cacheTtl.Value.Ticks / TimeSpan.TicksPerSecond, Int32.MaxValue);
|
cachePolicy.SecondsToLive = (uint)Math.Min(_cacheTtl.Value.Ticks / TimeSpan.TicksPerSecond, Int32.MaxValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -297,8 +298,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
fixed (byte* pReasonPhrase = reasonPhraseBytes)
|
fixed (byte* pReasonPhrase = reasonPhraseBytes)
|
||||||
{
|
{
|
||||||
_nativeResponse.Response_V1.ReasonLength = (ushort)reasonPhraseBytes.Length;
|
_nativeResponse.Response_V1.ReasonLength = (ushort)reasonPhraseBytes.Length;
|
||||||
_nativeResponse.Response_V1.pReason = (sbyte*)pReasonPhrase;
|
_nativeResponse.Response_V1.pReason = (byte*)pReasonPhrase;
|
||||||
fixed (HttpApi.HTTP_RESPONSE_V2* pResponse = &_nativeResponse)
|
fixed (HttpApiTypes.HTTP_RESPONSE_V2* pResponse = &_nativeResponse)
|
||||||
{
|
{
|
||||||
statusCode =
|
statusCode =
|
||||||
HttpApi.HttpSendHttpResponse(
|
HttpApi.HttpSendHttpResponse(
|
||||||
|
|
@ -330,14 +331,14 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
return statusCode;
|
return statusCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal HttpApi.HTTP_FLAGS ComputeHeaders(long writeCount, bool endOfRequest = false)
|
internal HttpApiTypes.HTTP_FLAGS ComputeHeaders(long writeCount, bool endOfRequest = false)
|
||||||
{
|
{
|
||||||
if (StatusCode == (ushort)StatusCodes.Status401Unauthorized)
|
if (StatusCode == (ushort)StatusCodes.Status401Unauthorized)
|
||||||
{
|
{
|
||||||
RequestContext.Server.Options.Authentication.SetAuthenticationChallenge(RequestContext);
|
RequestContext.Server.Options.Authentication.SetAuthenticationChallenge(RequestContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
var flags = HttpApi.HTTP_FLAGS.NONE;
|
var flags = HttpApiTypes.HTTP_FLAGS.NONE;
|
||||||
Debug.Assert(!HasComputedHeaders, nameof(HasComputedHeaders) + " is true.");
|
Debug.Assert(!HasComputedHeaders, nameof(HasComputedHeaders) + " is true.");
|
||||||
_responseState = ResponseState.ComputedHeaders;
|
_responseState = ResponseState.ComputedHeaders;
|
||||||
|
|
||||||
|
|
@ -414,7 +415,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
Headers.Append(HttpKnownHeaderNames.Connection, Constants.Close);
|
Headers.Append(HttpKnownHeaderNames.Connection, Constants.Close);
|
||||||
}
|
}
|
||||||
flags = HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT;
|
flags = HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
|
|
@ -428,8 +429,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
private unsafe List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
|
private unsafe List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
|
||||||
{
|
{
|
||||||
Headers.IsReadOnly = true; // Prohibit further modifications.
|
Headers.IsReadOnly = true; // Prohibit further modifications.
|
||||||
HttpApi.HTTP_UNKNOWN_HEADER[] unknownHeaders = null;
|
HttpApiTypes.HTTP_UNKNOWN_HEADER[] unknownHeaders = null;
|
||||||
HttpApi.HTTP_RESPONSE_INFO[] knownHeaderInfo = null;
|
HttpApiTypes.HTTP_RESPONSE_INFO[] knownHeaderInfo = null;
|
||||||
List<GCHandle> pinnedHeaders;
|
List<GCHandle> pinnedHeaders;
|
||||||
GCHandle gcHandle;
|
GCHandle gcHandle;
|
||||||
|
|
||||||
|
|
@ -452,11 +453,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// See if this is an unknown header
|
// See if this is an unknown header
|
||||||
lookup = HttpApi.HTTP_RESPONSE_HEADER_ID.IndexOfKnownHeader(headerPair.Key);
|
lookup = HttpApiTypes.HTTP_RESPONSE_HEADER_ID.IndexOfKnownHeader(headerPair.Key);
|
||||||
|
|
||||||
// Http.Sys doesn't let us send the Connection: Upgrade header as a Known header.
|
// Http.Sys doesn't let us send the Connection: Upgrade header as a Known header.
|
||||||
if (lookup == -1 ||
|
if (lookup == -1 ||
|
||||||
(isOpaqueUpgrade && lookup == (int)HttpApi.HTTP_RESPONSE_HEADER_ID.Enum.HttpHeaderConnection))
|
(isOpaqueUpgrade && lookup == (int)HttpApiTypes.HTTP_RESPONSE_HEADER_ID.Enum.HttpHeaderConnection))
|
||||||
{
|
{
|
||||||
numUnknownHeaders += headerPair.Value.Count;
|
numUnknownHeaders += headerPair.Value.Count;
|
||||||
}
|
}
|
||||||
|
|
@ -469,7 +470,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
fixed (HttpApi.HTTP_KNOWN_HEADER* pKnownHeaders = &_nativeResponse.Response_V1.Headers.KnownHeaders)
|
fixed (HttpApiTypes.HTTP_KNOWN_HEADER* pKnownHeaders = &_nativeResponse.Response_V1.Headers.KnownHeaders)
|
||||||
{
|
{
|
||||||
foreach (var headerPair in Headers)
|
foreach (var headerPair in Headers)
|
||||||
{
|
{
|
||||||
|
|
@ -479,18 +480,18 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
headerName = headerPair.Key;
|
headerName = headerPair.Key;
|
||||||
StringValues headerValues = headerPair.Value;
|
StringValues headerValues = headerPair.Value;
|
||||||
lookup = HttpApi.HTTP_RESPONSE_HEADER_ID.IndexOfKnownHeader(headerName);
|
lookup = HttpApiTypes.HTTP_RESPONSE_HEADER_ID.IndexOfKnownHeader(headerName);
|
||||||
|
|
||||||
// Http.Sys doesn't let us send the Connection: Upgrade header as a Known header.
|
// Http.Sys doesn't let us send the Connection: Upgrade header as a Known header.
|
||||||
if (lookup == -1 ||
|
if (lookup == -1 ||
|
||||||
(isOpaqueUpgrade && lookup == (int)HttpApi.HTTP_RESPONSE_HEADER_ID.Enum.HttpHeaderConnection))
|
(isOpaqueUpgrade && lookup == (int)HttpApiTypes.HTTP_RESPONSE_HEADER_ID.Enum.HttpHeaderConnection))
|
||||||
{
|
{
|
||||||
if (unknownHeaders == null)
|
if (unknownHeaders == null)
|
||||||
{
|
{
|
||||||
unknownHeaders = new HttpApi.HTTP_UNKNOWN_HEADER[numUnknownHeaders];
|
unknownHeaders = new HttpApiTypes.HTTP_UNKNOWN_HEADER[numUnknownHeaders];
|
||||||
gcHandle = GCHandle.Alloc(unknownHeaders, GCHandleType.Pinned);
|
gcHandle = GCHandle.Alloc(unknownHeaders, GCHandleType.Pinned);
|
||||||
pinnedHeaders.Add(gcHandle);
|
pinnedHeaders.Add(gcHandle);
|
||||||
_nativeResponse.Response_V1.Headers.pUnknownHeaders = (HttpApi.HTTP_UNKNOWN_HEADER*)gcHandle.AddrOfPinnedObject();
|
_nativeResponse.Response_V1.Headers.pUnknownHeaders = (HttpApiTypes.HTTP_UNKNOWN_HEADER*)gcHandle.AddrOfPinnedObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int headerValueIndex = 0; headerValueIndex < headerValues.Count; headerValueIndex++)
|
for (int headerValueIndex = 0; headerValueIndex < headerValues.Count; headerValueIndex++)
|
||||||
|
|
@ -500,7 +501,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
unknownHeaders[_nativeResponse.Response_V1.Headers.UnknownHeaderCount].NameLength = (ushort)bytes.Length;
|
unknownHeaders[_nativeResponse.Response_V1.Headers.UnknownHeaderCount].NameLength = (ushort)bytes.Length;
|
||||||
gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
||||||
pinnedHeaders.Add(gcHandle);
|
pinnedHeaders.Add(gcHandle);
|
||||||
unknownHeaders[_nativeResponse.Response_V1.Headers.UnknownHeaderCount].pName = (sbyte*)gcHandle.AddrOfPinnedObject();
|
unknownHeaders[_nativeResponse.Response_V1.Headers.UnknownHeaderCount].pName = (byte*)gcHandle.AddrOfPinnedObject();
|
||||||
|
|
||||||
// Add Value
|
// Add Value
|
||||||
headerValue = headerValues[headerValueIndex] ?? string.Empty;
|
headerValue = headerValues[headerValueIndex] ?? string.Empty;
|
||||||
|
|
@ -508,7 +509,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
unknownHeaders[_nativeResponse.Response_V1.Headers.UnknownHeaderCount].RawValueLength = (ushort)bytes.Length;
|
unknownHeaders[_nativeResponse.Response_V1.Headers.UnknownHeaderCount].RawValueLength = (ushort)bytes.Length;
|
||||||
gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
||||||
pinnedHeaders.Add(gcHandle);
|
pinnedHeaders.Add(gcHandle);
|
||||||
unknownHeaders[_nativeResponse.Response_V1.Headers.UnknownHeaderCount].pRawValue = (sbyte*)gcHandle.AddrOfPinnedObject();
|
unknownHeaders[_nativeResponse.Response_V1.Headers.UnknownHeaderCount].pRawValue = (byte*)gcHandle.AddrOfPinnedObject();
|
||||||
_nativeResponse.Response_V1.Headers.UnknownHeaderCount++;
|
_nativeResponse.Response_V1.Headers.UnknownHeaderCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -519,30 +520,30 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
pKnownHeaders[lookup].RawValueLength = (ushort)bytes.Length;
|
pKnownHeaders[lookup].RawValueLength = (ushort)bytes.Length;
|
||||||
gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
||||||
pinnedHeaders.Add(gcHandle);
|
pinnedHeaders.Add(gcHandle);
|
||||||
pKnownHeaders[lookup].pRawValue = (sbyte*)gcHandle.AddrOfPinnedObject();
|
pKnownHeaders[lookup].pRawValue = (byte*)gcHandle.AddrOfPinnedObject();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (knownHeaderInfo == null)
|
if (knownHeaderInfo == null)
|
||||||
{
|
{
|
||||||
knownHeaderInfo = new HttpApi.HTTP_RESPONSE_INFO[numKnownMultiHeaders];
|
knownHeaderInfo = new HttpApiTypes.HTTP_RESPONSE_INFO[numKnownMultiHeaders];
|
||||||
gcHandle = GCHandle.Alloc(knownHeaderInfo, GCHandleType.Pinned);
|
gcHandle = GCHandle.Alloc(knownHeaderInfo, GCHandleType.Pinned);
|
||||||
pinnedHeaders.Add(gcHandle);
|
pinnedHeaders.Add(gcHandle);
|
||||||
_nativeResponse.pResponseInfo = (HttpApi.HTTP_RESPONSE_INFO*)gcHandle.AddrOfPinnedObject();
|
_nativeResponse.pResponseInfo = (HttpApiTypes.HTTP_RESPONSE_INFO*)gcHandle.AddrOfPinnedObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
knownHeaderInfo[_nativeResponse.ResponseInfoCount].Type = HttpApi.HTTP_RESPONSE_INFO_TYPE.HttpResponseInfoTypeMultipleKnownHeaders;
|
knownHeaderInfo[_nativeResponse.ResponseInfoCount].Type = HttpApiTypes.HTTP_RESPONSE_INFO_TYPE.HttpResponseInfoTypeMultipleKnownHeaders;
|
||||||
knownHeaderInfo[_nativeResponse.ResponseInfoCount].Length = (uint)Marshal.SizeOf<HttpApi.HTTP_MULTIPLE_KNOWN_HEADERS>();
|
knownHeaderInfo[_nativeResponse.ResponseInfoCount].Length = (uint)Marshal.SizeOf<HttpApiTypes.HTTP_MULTIPLE_KNOWN_HEADERS>();
|
||||||
|
|
||||||
HttpApi.HTTP_MULTIPLE_KNOWN_HEADERS header = new HttpApi.HTTP_MULTIPLE_KNOWN_HEADERS();
|
HttpApiTypes.HTTP_MULTIPLE_KNOWN_HEADERS header = new HttpApiTypes.HTTP_MULTIPLE_KNOWN_HEADERS();
|
||||||
|
|
||||||
header.HeaderId = (HttpApi.HTTP_RESPONSE_HEADER_ID.Enum)lookup;
|
header.HeaderId = (HttpApiTypes.HTTP_RESPONSE_HEADER_ID.Enum)lookup;
|
||||||
header.Flags = HttpApi.HTTP_RESPONSE_INFO_FLAGS.PreserveOrder; // TODO: The docs say this is for www-auth only.
|
header.Flags = HttpApiTypes.HTTP_RESPONSE_INFO_FLAGS.PreserveOrder; // TODO: The docs say this is for www-auth only.
|
||||||
|
|
||||||
HttpApi.HTTP_KNOWN_HEADER[] nativeHeaderValues = new HttpApi.HTTP_KNOWN_HEADER[headerValues.Count];
|
HttpApiTypes.HTTP_KNOWN_HEADER[] nativeHeaderValues = new HttpApiTypes.HTTP_KNOWN_HEADER[headerValues.Count];
|
||||||
gcHandle = GCHandle.Alloc(nativeHeaderValues, GCHandleType.Pinned);
|
gcHandle = GCHandle.Alloc(nativeHeaderValues, GCHandleType.Pinned);
|
||||||
pinnedHeaders.Add(gcHandle);
|
pinnedHeaders.Add(gcHandle);
|
||||||
header.KnownHeaders = (HttpApi.HTTP_KNOWN_HEADER*)gcHandle.AddrOfPinnedObject();
|
header.KnownHeaders = (HttpApiTypes.HTTP_KNOWN_HEADER*)gcHandle.AddrOfPinnedObject();
|
||||||
|
|
||||||
for (int headerValueIndex = 0; headerValueIndex < headerValues.Count; headerValueIndex++)
|
for (int headerValueIndex = 0; headerValueIndex < headerValues.Count; headerValueIndex++)
|
||||||
{
|
{
|
||||||
|
|
@ -552,14 +553,14 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
nativeHeaderValues[header.KnownHeaderCount].RawValueLength = (ushort)bytes.Length;
|
nativeHeaderValues[header.KnownHeaderCount].RawValueLength = (ushort)bytes.Length;
|
||||||
gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
||||||
pinnedHeaders.Add(gcHandle);
|
pinnedHeaders.Add(gcHandle);
|
||||||
nativeHeaderValues[header.KnownHeaderCount].pRawValue = (sbyte*)gcHandle.AddrOfPinnedObject();
|
nativeHeaderValues[header.KnownHeaderCount].pRawValue = (byte*)gcHandle.AddrOfPinnedObject();
|
||||||
header.KnownHeaderCount++;
|
header.KnownHeaderCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This type is a struct, not an object, so pinning it causes a boxed copy to be created. We can't do that until after all the fields are set.
|
// This type is a struct, not an object, so pinning it causes a boxed copy to be created. We can't do that until after all the fields are set.
|
||||||
gcHandle = GCHandle.Alloc(header, GCHandleType.Pinned);
|
gcHandle = GCHandle.Alloc(header, GCHandleType.Pinned);
|
||||||
pinnedHeaders.Add(gcHandle);
|
pinnedHeaders.Add(gcHandle);
|
||||||
knownHeaderInfo[_nativeResponse.ResponseInfoCount].pInfo = (HttpApi.HTTP_MULTIPLE_KNOWN_HEADERS*)gcHandle.AddrOfPinnedObject();
|
knownHeaderInfo[_nativeResponse.ResponseInfoCount].pInfo = (HttpApiTypes.HTTP_MULTIPLE_KNOWN_HEADERS*)gcHandle.AddrOfPinnedObject();
|
||||||
|
|
||||||
_nativeResponse.ResponseInfoCount++;
|
_nativeResponse.ResponseInfoCount++;
|
||||||
}
|
}
|
||||||
|
|
@ -595,9 +596,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
||||||
// TODO: Send headers async?
|
// TODO: Send headers async?
|
||||||
ulong errorCode = SendHeaders(null, null,
|
ulong errorCode = SendHeaders(null, null,
|
||||||
HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_OPAQUE |
|
HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_OPAQUE |
|
||||||
HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA |
|
HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA |
|
||||||
HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA,
|
HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_BUFFER_DATA,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
if (errorCode != ErrorCodes.ERROR_SUCCESS)
|
if (errorCode != ErrorCodes.ERROR_SUCCESS)
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,9 @@ using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using static Microsoft.AspNetCore.Server.HttpSys.UnsafeNclNativeMethods;
|
using static Microsoft.AspNetCore.HttpSys.Internal.UnsafeNclNativeMethods;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
|
|
@ -132,7 +133,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
|
|
||||||
uint statusCode = 0;
|
uint statusCode = 0;
|
||||||
HttpApi.HTTP_DATA_CHUNK[] dataChunks;
|
HttpApiTypes.HTTP_DATA_CHUNK[] dataChunks;
|
||||||
var pinnedBuffers = PinDataBuffers(endOfRequest, data, out dataChunks);
|
var pinnedBuffers = PinDataBuffers(endOfRequest, data, out dataChunks);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -142,7 +143,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fixed (HttpApi.HTTP_DATA_CHUNK* pDataChunks = dataChunks)
|
fixed (HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks = dataChunks)
|
||||||
{
|
{
|
||||||
statusCode = HttpApi.HttpSendResponseEntityBody(
|
statusCode = HttpApi.HttpSendResponseEntityBody(
|
||||||
RequestQueueHandle,
|
RequestQueueHandle,
|
||||||
|
|
@ -183,7 +184,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<GCHandle> PinDataBuffers(bool endOfRequest, ArraySegment<byte> data, out HttpApi.HTTP_DATA_CHUNK[] dataChunks)
|
private List<GCHandle> PinDataBuffers(bool endOfRequest, ArraySegment<byte> data, out HttpApiTypes.HTTP_DATA_CHUNK[] dataChunks)
|
||||||
{
|
{
|
||||||
var pins = new List<GCHandle>();
|
var pins = new List<GCHandle>();
|
||||||
var chunked = _requestContext.Response.BoundaryType == BoundaryType.Chunked;
|
var chunked = _requestContext.Response.BoundaryType == BoundaryType.Chunked;
|
||||||
|
|
@ -192,14 +193,14 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
// Figure out how many data chunks
|
// Figure out how many data chunks
|
||||||
if (chunked && data.Count == 0 && endOfRequest)
|
if (chunked && data.Count == 0 && endOfRequest)
|
||||||
{
|
{
|
||||||
dataChunks = new HttpApi.HTTP_DATA_CHUNK[1];
|
dataChunks = new HttpApiTypes.HTTP_DATA_CHUNK[1];
|
||||||
SetDataChunk(dataChunks, ref currentChunk, pins, new ArraySegment<byte>(Helpers.ChunkTerminator));
|
SetDataChunk(dataChunks, ref currentChunk, pins, new ArraySegment<byte>(Helpers.ChunkTerminator));
|
||||||
return pins;
|
return pins;
|
||||||
}
|
}
|
||||||
else if (data.Count == 0)
|
else if (data.Count == 0)
|
||||||
{
|
{
|
||||||
// No data
|
// No data
|
||||||
dataChunks = new HttpApi.HTTP_DATA_CHUNK[0];
|
dataChunks = new HttpApiTypes.HTTP_DATA_CHUNK[0];
|
||||||
return pins;
|
return pins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -215,7 +216,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
chunkCount += 1;
|
chunkCount += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dataChunks = new HttpApi.HTTP_DATA_CHUNK[chunkCount];
|
dataChunks = new HttpApiTypes.HTTP_DATA_CHUNK[chunkCount];
|
||||||
|
|
||||||
if (chunked)
|
if (chunked)
|
||||||
{
|
{
|
||||||
|
|
@ -238,11 +239,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
return pins;
|
return pins;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetDataChunk(HttpApi.HTTP_DATA_CHUNK[] chunks, ref int chunkIndex, List<GCHandle> pins, ArraySegment<byte> buffer)
|
private static void SetDataChunk(HttpApiTypes.HTTP_DATA_CHUNK[] chunks, ref int chunkIndex, List<GCHandle> pins, ArraySegment<byte> buffer)
|
||||||
{
|
{
|
||||||
var handle = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned);
|
var handle = GCHandle.Alloc(buffer.Array, GCHandleType.Pinned);
|
||||||
pins.Add(handle);
|
pins.Add(handle);
|
||||||
chunks[chunkIndex].DataChunkType = HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
|
chunks[chunkIndex].DataChunkType = HttpApiTypes.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
|
||||||
chunks[chunkIndex].fromMemory.pBuffer = handle.AddrOfPinnedObject() + buffer.Offset;
|
chunks[chunkIndex].fromMemory.pBuffer = handle.AddrOfPinnedObject() + buffer.Offset;
|
||||||
chunks[chunkIndex].fromMemory.BufferLength = (uint)buffer.Count;
|
chunks[chunkIndex].fromMemory.BufferLength = (uint)buffer.Count;
|
||||||
chunkIndex++;
|
chunkIndex++;
|
||||||
|
|
@ -355,7 +356,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last write, cache it for special cancellation handling.
|
// Last write, cache it for special cancellation handling.
|
||||||
if ((flags & HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0)
|
if ((flags & HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0)
|
||||||
{
|
{
|
||||||
_lastWrite = asyncResult;
|
_lastWrite = asyncResult;
|
||||||
}
|
}
|
||||||
|
|
@ -405,9 +406,9 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
_requestContext.Abort();
|
_requestContext.Abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpApi.HTTP_FLAGS ComputeLeftToWrite(long writeCount, bool endOfRequest = false)
|
private HttpApiTypes.HTTP_FLAGS ComputeLeftToWrite(long writeCount, bool endOfRequest = false)
|
||||||
{
|
{
|
||||||
var flags = HttpApi.HTTP_FLAGS.NONE;
|
var flags = HttpApiTypes.HTTP_FLAGS.NONE;
|
||||||
if (!_requestContext.Response.HasComputedHeaders)
|
if (!_requestContext.Response.HasComputedHeaders)
|
||||||
{
|
{
|
||||||
flags = _requestContext.Response.ComputeHeaders(writeCount, endOfRequest);
|
flags = _requestContext.Response.ComputeHeaders(writeCount, endOfRequest);
|
||||||
|
|
@ -430,11 +431,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
||||||
if (endOfRequest && _requestContext.Response.BoundaryType == BoundaryType.Close)
|
if (endOfRequest && _requestContext.Response.BoundaryType == BoundaryType.Close)
|
||||||
{
|
{
|
||||||
flags |= HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT;
|
flags |= HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT;
|
||||||
}
|
}
|
||||||
else if (!endOfRequest && _leftToWrite != writeCount)
|
else if (!endOfRequest && _leftToWrite != writeCount)
|
||||||
{
|
{
|
||||||
flags |= HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA;
|
flags |= HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update _leftToWrite now so we can queue up additional async writes.
|
// Update _leftToWrite now so we can queue up additional async writes.
|
||||||
|
|
@ -647,7 +648,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last write, cache it for special cancellation handling.
|
// Last write, cache it for special cancellation handling.
|
||||||
if ((flags & HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0)
|
if ((flags & HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0)
|
||||||
{
|
{
|
||||||
_lastWrite = asyncResult;
|
_lastWrite = asyncResult;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using static Microsoft.AspNetCore.Server.HttpSys.UnsafeNclNativeMethods;
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
private static readonly IOCompletionCallback IOCallback = new IOCompletionCallback(Callback);
|
private static readonly IOCompletionCallback IOCallback = new IOCompletionCallback(Callback);
|
||||||
|
|
||||||
private SafeNativeOverlapped _overlapped;
|
private SafeNativeOverlapped _overlapped;
|
||||||
private HttpApi.HTTP_DATA_CHUNK[] _dataChunks;
|
private HttpApiTypes.HTTP_DATA_CHUNK[] _dataChunks;
|
||||||
private FileStream _fileStream;
|
private FileStream _fileStream;
|
||||||
private ResponseBody _responseStream;
|
private ResponseBody _responseStream;
|
||||||
private TaskCompletionSource<object> _tcs;
|
private TaskCompletionSource<object> _tcs;
|
||||||
|
|
@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_dataChunks = new HttpApi.HTTP_DATA_CHUNK[1 + (chunked ? 2 : 0)];
|
_dataChunks = new HttpApiTypes.HTTP_DATA_CHUNK[1 + (chunked ? 2 : 0)];
|
||||||
objectsToPin = new object[_dataChunks.Length + 1];
|
objectsToPin = new object[_dataChunks.Length + 1];
|
||||||
objectsToPin[0] = _dataChunks;
|
objectsToPin[0] = _dataChunks;
|
||||||
var currentChunk = 0;
|
var currentChunk = 0;
|
||||||
|
|
@ -110,7 +110,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_dataChunks = new HttpApi.HTTP_DATA_CHUNK[chunked ? 3 : 1];
|
_dataChunks = new HttpApiTypes.HTTP_DATA_CHUNK[chunked ? 3 : 1];
|
||||||
|
|
||||||
object[] objectsToPin = new object[_dataChunks.Length];
|
object[] objectsToPin = new object[_dataChunks.Length];
|
||||||
objectsToPin[_dataChunks.Length - 1] = _dataChunks;
|
objectsToPin[_dataChunks.Length - 1] = _dataChunks;
|
||||||
|
|
@ -119,23 +119,23 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
if (chunked)
|
if (chunked)
|
||||||
{
|
{
|
||||||
chunkHeaderBuffer = Helpers.GetChunkHeader(count);
|
chunkHeaderBuffer = Helpers.GetChunkHeader(count);
|
||||||
_dataChunks[0].DataChunkType = HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
|
_dataChunks[0].DataChunkType = HttpApiTypes.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
|
||||||
_dataChunks[0].fromMemory.BufferLength = (uint)chunkHeaderBuffer.Count;
|
_dataChunks[0].fromMemory.BufferLength = (uint)chunkHeaderBuffer.Count;
|
||||||
objectsToPin[0] = chunkHeaderBuffer.Array;
|
objectsToPin[0] = chunkHeaderBuffer.Array;
|
||||||
|
|
||||||
_dataChunks[1].DataChunkType = HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromFileHandle;
|
_dataChunks[1].DataChunkType = HttpApiTypes.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromFileHandle;
|
||||||
_dataChunks[1].fromFile.offset = (ulong)offset;
|
_dataChunks[1].fromFile.offset = (ulong)offset;
|
||||||
_dataChunks[1].fromFile.count = (ulong)count;
|
_dataChunks[1].fromFile.count = (ulong)count;
|
||||||
_dataChunks[1].fromFile.fileHandle = _fileStream.SafeFileHandle.DangerousGetHandle();
|
_dataChunks[1].fromFile.fileHandle = _fileStream.SafeFileHandle.DangerousGetHandle();
|
||||||
// Nothing to pin for the file handle.
|
// Nothing to pin for the file handle.
|
||||||
|
|
||||||
_dataChunks[2].DataChunkType = HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
|
_dataChunks[2].DataChunkType = HttpApiTypes.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
|
||||||
_dataChunks[2].fromMemory.BufferLength = (uint)Helpers.CRLF.Length;
|
_dataChunks[2].fromMemory.BufferLength = (uint)Helpers.CRLF.Length;
|
||||||
objectsToPin[1] = Helpers.CRLF;
|
objectsToPin[1] = Helpers.CRLF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_dataChunks[0].DataChunkType = HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromFileHandle;
|
_dataChunks[0].DataChunkType = HttpApiTypes.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromFileHandle;
|
||||||
_dataChunks[0].fromFile.offset = (ulong)offset;
|
_dataChunks[0].fromFile.offset = (ulong)offset;
|
||||||
_dataChunks[0].fromFile.count = (ulong)count;
|
_dataChunks[0].fromFile.count = (ulong)count;
|
||||||
_dataChunks[0].fromFile.fileHandle = _fileStream.SafeFileHandle.DangerousGetHandle();
|
_dataChunks[0].fromFile.fileHandle = _fileStream.SafeFileHandle.DangerousGetHandle();
|
||||||
|
|
@ -154,11 +154,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetDataChunk(HttpApi.HTTP_DATA_CHUNK[] chunks, ref int chunkIndex, object[] objectsToPin, ref int pinIndex, ArraySegment<byte> segment)
|
private static void SetDataChunk(HttpApiTypes.HTTP_DATA_CHUNK[] chunks, ref int chunkIndex, object[] objectsToPin, ref int pinIndex, ArraySegment<byte> segment)
|
||||||
{
|
{
|
||||||
objectsToPin[pinIndex] = segment.Array;
|
objectsToPin[pinIndex] = segment.Array;
|
||||||
pinIndex++;
|
pinIndex++;
|
||||||
chunks[chunkIndex].DataChunkType = HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
|
chunks[chunkIndex].DataChunkType = HttpApiTypes.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
|
||||||
// The address is not set until after we pin it with Overlapped
|
// The address is not set until after we pin it with Overlapped
|
||||||
chunks[chunkIndex].fromMemory.BufferLength = (uint)segment.Count;
|
chunks[chunkIndex].fromMemory.BufferLength = (uint)segment.Count;
|
||||||
chunkIndex++;
|
chunkIndex++;
|
||||||
|
|
@ -195,7 +195,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal HttpApi.HTTP_DATA_CHUNK* DataChunks
|
internal HttpApiTypes.HTTP_DATA_CHUNK* DataChunks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
|
@ -205,7 +205,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return (HttpApi.HTTP_DATA_CHUNK*)(Marshal.UnsafeAddrOfPinnedArrayElement(_dataChunks, 0));
|
return (HttpApiTypes.HTTP_DATA_CHUNK*)(Marshal.UnsafeAddrOfPinnedArrayElement(_dataChunks, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
|
|
@ -15,7 +16,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
public sealed class TimeoutManager
|
public sealed class TimeoutManager
|
||||||
{
|
{
|
||||||
private static readonly int TimeoutLimitSize =
|
private static readonly int TimeoutLimitSize =
|
||||||
Marshal.SizeOf<HttpApi.HTTP_TIMEOUT_LIMIT_INFO>();
|
Marshal.SizeOf<HttpApiTypes.HTTP_TIMEOUT_LIMIT_INFO>();
|
||||||
|
|
||||||
private UrlGroup _urlGroup;
|
private UrlGroup _urlGroup;
|
||||||
private int[] _timeouts;
|
private int[] _timeouts;
|
||||||
|
|
@ -47,11 +48,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return GetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.EntityBody);
|
return GetTimeSpanTimeout(HttpApiTypes.HTTP_TIMEOUT_TYPE.EntityBody);
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.EntityBody, value);
|
SetTimeSpanTimeout(HttpApiTypes.HTTP_TIMEOUT_TYPE.EntityBody, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,11 +71,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return GetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.DrainEntityBody);
|
return GetTimeSpanTimeout(HttpApiTypes.HTTP_TIMEOUT_TYPE.DrainEntityBody);
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.DrainEntityBody, value);
|
SetTimeSpanTimeout(HttpApiTypes.HTTP_TIMEOUT_TYPE.DrainEntityBody, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,11 +89,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return GetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.RequestQueue);
|
return GetTimeSpanTimeout(HttpApiTypes.HTTP_TIMEOUT_TYPE.RequestQueue);
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.RequestQueue, value);
|
SetTimeSpanTimeout(HttpApiTypes.HTTP_TIMEOUT_TYPE.RequestQueue, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,11 +108,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return GetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.IdleConnection);
|
return GetTimeSpanTimeout(HttpApiTypes.HTTP_TIMEOUT_TYPE.IdleConnection);
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.IdleConnection, value);
|
SetTimeSpanTimeout(HttpApiTypes.HTTP_TIMEOUT_TYPE.IdleConnection, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,11 +128,11 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return GetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait);
|
return GetTimeSpanTimeout(HttpApiTypes.HTTP_TIMEOUT_TYPE.HeaderWait);
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
SetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait, value);
|
SetTimeSpanTimeout(HttpApiTypes.HTTP_TIMEOUT_TYPE.HeaderWait, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,13 +168,13 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
|
|
||||||
#region Helpers
|
#region Helpers
|
||||||
|
|
||||||
private TimeSpan GetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE type)
|
private TimeSpan GetTimeSpanTimeout(HttpApiTypes.HTTP_TIMEOUT_TYPE type)
|
||||||
{
|
{
|
||||||
// Since we maintain local state, GET is local.
|
// Since we maintain local state, GET is local.
|
||||||
return new TimeSpan(0, 0, (int)_timeouts[(int)type]);
|
return new TimeSpan(0, 0, (int)_timeouts[(int)type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetTimeSpanTimeout(HttpApi.HTTP_TIMEOUT_TYPE type, TimeSpan value)
|
private void SetTimeSpanTimeout(HttpApiTypes.HTTP_TIMEOUT_TYPE type, TimeSpan value)
|
||||||
{
|
{
|
||||||
// All timeouts are defined as USHORT in native layer (except MinSendRate, which is ULONG). Make sure that
|
// All timeouts are defined as USHORT in native layer (except MinSendRate, which is ULONG). Make sure that
|
||||||
// timeout value is within range.
|
// timeout value is within range.
|
||||||
|
|
@ -207,25 +208,25 @@ namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var timeoutinfo = new HttpApi.HTTP_TIMEOUT_LIMIT_INFO();
|
var timeoutinfo = new HttpApiTypes.HTTP_TIMEOUT_LIMIT_INFO();
|
||||||
|
|
||||||
timeoutinfo.Flags = HttpApi.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT;
|
timeoutinfo.Flags = HttpApiTypes.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT;
|
||||||
timeoutinfo.DrainEntityBody =
|
timeoutinfo.DrainEntityBody =
|
||||||
(ushort)timeouts[(int)HttpApi.HTTP_TIMEOUT_TYPE.DrainEntityBody];
|
(ushort)timeouts[(int)HttpApiTypes.HTTP_TIMEOUT_TYPE.DrainEntityBody];
|
||||||
timeoutinfo.EntityBody =
|
timeoutinfo.EntityBody =
|
||||||
(ushort)timeouts[(int)HttpApi.HTTP_TIMEOUT_TYPE.EntityBody];
|
(ushort)timeouts[(int)HttpApiTypes.HTTP_TIMEOUT_TYPE.EntityBody];
|
||||||
timeoutinfo.RequestQueue =
|
timeoutinfo.RequestQueue =
|
||||||
(ushort)timeouts[(int)HttpApi.HTTP_TIMEOUT_TYPE.RequestQueue];
|
(ushort)timeouts[(int)HttpApiTypes.HTTP_TIMEOUT_TYPE.RequestQueue];
|
||||||
timeoutinfo.IdleConnection =
|
timeoutinfo.IdleConnection =
|
||||||
(ushort)timeouts[(int)HttpApi.HTTP_TIMEOUT_TYPE.IdleConnection];
|
(ushort)timeouts[(int)HttpApiTypes.HTTP_TIMEOUT_TYPE.IdleConnection];
|
||||||
timeoutinfo.HeaderWait =
|
timeoutinfo.HeaderWait =
|
||||||
(ushort)timeouts[(int)HttpApi.HTTP_TIMEOUT_TYPE.HeaderWait];
|
(ushort)timeouts[(int)HttpApiTypes.HTTP_TIMEOUT_TYPE.HeaderWait];
|
||||||
timeoutinfo.MinSendRate = minSendBytesPerSecond;
|
timeoutinfo.MinSendRate = minSendBytesPerSecond;
|
||||||
|
|
||||||
var infoptr = new IntPtr(&timeoutinfo);
|
var infoptr = new IntPtr(&timeoutinfo);
|
||||||
|
|
||||||
_urlGroup.SetProperty(
|
_urlGroup.SetProperty(
|
||||||
HttpApi.HTTP_SERVER_PROPERTY.HttpServerTimeoutsProperty,
|
HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerTimeoutsProperty,
|
||||||
infoptr, (uint)TimeoutLimitSize);
|
infoptr, (uint)TimeoutLimitSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Server.HttpSys
|
namespace Microsoft.AspNetCore.Server.HttpSys
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Hosting.Server.Features;
|
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using Microsoft.AspNetCore.Testing.xunit;
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Hosting.Server;
|
using Microsoft.AspNetCore.Hosting.Server;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Http.Features;
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
|
using Microsoft.AspNetCore.HttpSys.Internal;
|
||||||
using Microsoft.AspNetCore.Testing.xunit;
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue