Skip to content

Commit 7f18f8f

Browse files
authored
Use generated PInvokes and exchange types (#50685)
1 parent e5467fc commit 7f18f8f

File tree

69 files changed

+1036
-2507
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1036
-2507
lines changed

eng/Dependencies.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ and are generated based on the last package release.
200200
<LatestPackageReference Include="MessagePack" />
201201
<LatestPackageReference Include="MessagePackAnalyzer" />
202202
<LatestPackageReference Include="Microsoft.Data.SqlClient" />
203+
<LatestPackageReference Include="Microsoft.Windows.CsWin32" />
203204
<LatestPackageReference Include="Mono.Cecil" />
204205
<LatestPackageReference Include="Mono.TextTemplating" />
205206
<LatestPackageReference Include="Moq" />

eng/Versions.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@
302302
<MicrosoftIdentityWebGraphServiceClientVersion>2.13.4</MicrosoftIdentityWebGraphServiceClientVersion>
303303
<MicrosoftIdentityWebUIVersion>2.13.4</MicrosoftIdentityWebUIVersion>
304304
<MicrosoftIdentityWebDownstreamApiVersion>2.13.4</MicrosoftIdentityWebDownstreamApiVersion>
305+
<MicrosoftWindowsCsWin32Version>0.3.46-beta</MicrosoftWindowsCsWin32Version>
305306
<MessagePackAnalyzerVersion>$(MessagePackVersion)</MessagePackAnalyzerVersion>
306307
<MoqVersion>4.10.0</MoqVersion>
307308
<MonoCecilVersion>0.11.2</MonoCecilVersion>

src/Servers/HttpSys/HttpSysServer.slnf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"solution": {
33
"path": "..\\..\\..\\AspNetCore.sln",
44
"projects": [
5+
"src\\Antiforgery\\src\\Microsoft.AspNetCore.Antiforgery.csproj",
56
"src\\DataProtection\\Abstractions\\src\\Microsoft.AspNetCore.DataProtection.Abstractions.csproj",
67
"src\\DataProtection\\Cryptography.Internal\\src\\Microsoft.AspNetCore.Cryptography.Internal.csproj",
78
"src\\DataProtection\\DataProtection\\src\\Microsoft.AspNetCore.DataProtection.csproj",

src/Servers/HttpSys/perf/Microbenchmarks/RequestHeaderBenchmarks.cs

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
using System.Text;
77
using BenchmarkDotNet.Attributes;
88
using Microsoft.AspNetCore.HttpSys.Internal;
9+
using Windows.Win32.Foundation;
10+
using Windows.Win32.Networking.HttpServer;
911
using RequestHeaders = Microsoft.AspNetCore.HttpSys.Internal.RequestHeaders;
1012

1113
[SimpleJob, MemoryDiagnoser]
@@ -54,7 +56,7 @@ private unsafe RequestHeaders CreateRequestHeader(int unknowHeaderCount)
5456
var nativeContext = new NativeRequestContext(MemoryPool<byte>.Shared, null, 0, false);
5557
var nativeMemory = new Span<byte>(nativeContext.NativeRequest, (int)nativeContext.Size + 8);
5658

57-
var requestStructure = new HttpApiTypes.HTTP_REQUEST();
59+
var requestStructure = new HTTP_REQUEST_V1();
5860
var remainingMemory = SetUnknownHeaders(nativeMemory, ref requestStructure, GenerateUnknownHeaders(unknowHeaderCount));
5961
SetHostHeader(remainingMemory, ref requestStructure);
6062
MemoryMarshal.Write(nativeMemory, in requestStructure);
@@ -64,64 +66,64 @@ private unsafe RequestHeaders CreateRequestHeader(int unknowHeaderCount)
6466
return requestHeaders;
6567
}
6668

67-
private unsafe Span<byte> SetHostHeader(Span<byte> nativeMemory, ref HttpApiTypes.HTTP_REQUEST requestStructure)
69+
private unsafe Span<byte> SetHostHeader(Span<byte> nativeMemory, ref HTTP_REQUEST_V1 requestStructure)
6870
{
6971
// Writing localhost to Host header
70-
var dataDestination = nativeMemory.Slice(Marshal.SizeOf<HttpApiTypes.HTTP_REQUEST>());
71-
int length = Encoding.ASCII.GetBytes("localhost:5001", dataDestination);
72+
var dataDestination = nativeMemory[Marshal.SizeOf<HTTP_REQUEST_V1>()..];
73+
var length = Encoding.ASCII.GetBytes("localhost:5001", dataDestination);
7274
fixed (byte* address = &MemoryMarshal.GetReference(dataDestination))
7375
{
74-
requestStructure.Headers.KnownHeaders_29.pRawValue = address;
75-
requestStructure.Headers.KnownHeaders_29.RawValueLength = (ushort)length;
76+
requestStructure.Headers.KnownHeaders._28.pRawValue = (PCSTR)address;
77+
requestStructure.Headers.KnownHeaders._28.RawValueLength = (ushort)length;
7678
}
7779
return dataDestination;
7880
}
7981

8082
/// <summary>
8183
/// Writes an array HTTP_UNKNOWN_HEADER and an array of header key-value pairs to nativeMemory. Pointers in the HTTP_UNKNOWN_HEADER structure points to the corresponding key-value pair.
8284
/// </summary>
83-
private unsafe Span<byte> SetUnknownHeaders(Span<byte> nativeMemory, ref HttpApiTypes.HTTP_REQUEST requestStructure, IReadOnlyCollection<(string Key, string Value)> headerNames)
85+
private unsafe Span<byte> SetUnknownHeaders(Span<byte> nativeMemory, ref HTTP_REQUEST_V1 requestStructure, IReadOnlyCollection<(string Key, string Value)> headerNames)
8486
{
85-
var unknownHeaderStructureDestination = nativeMemory.Slice(Marshal.SizeOf<HttpApiTypes.HTTP_REQUEST>());
87+
var unknownHeaderStructureDestination = nativeMemory[Marshal.SizeOf<HTTP_REQUEST_V1>()..];
8688
fixed (byte* address = &MemoryMarshal.GetReference(unknownHeaderStructureDestination))
8789
{
88-
requestStructure.Headers.pUnknownHeaders = (HttpApiTypes.HTTP_UNKNOWN_HEADER*)address;
90+
requestStructure.Headers.pUnknownHeaders = (HTTP_UNKNOWN_HEADER*)address;
8991
}
9092
requestStructure.Headers.UnknownHeaderCount += (ushort)headerNames.Count;
9193

92-
var unknownHeadersSize = Marshal.SizeOf<HttpApiTypes.HTTP_UNKNOWN_HEADER>();
93-
var dataDestination = unknownHeaderStructureDestination.Slice(unknownHeadersSize * headerNames.Count);
94-
foreach (var headerName in headerNames)
94+
var unknownHeadersSize = Marshal.SizeOf<HTTP_UNKNOWN_HEADER>();
95+
var dataDestination = unknownHeaderStructureDestination[(unknownHeadersSize * headerNames.Count)..];
96+
foreach (var (headerKey, headerValue) in headerNames)
9597
{
96-
var unknownHeaderStructure = new HttpApiTypes.HTTP_UNKNOWN_HEADER();
97-
int nameLength = Encoding.ASCII.GetBytes(headerName.Key, dataDestination);
98+
var unknownHeaderStructure = new HTTP_UNKNOWN_HEADER();
99+
var nameLength = Encoding.ASCII.GetBytes(headerKey, dataDestination);
98100
fixed (byte* address = &MemoryMarshal.GetReference(dataDestination))
99101
{
100-
unknownHeaderStructure.pName = address;
102+
unknownHeaderStructure.pName = (PCSTR)address;
101103
unknownHeaderStructure.NameLength = (ushort)nameLength;
102104
}
103-
dataDestination = dataDestination.Slice(nameLength);
105+
dataDestination = dataDestination[nameLength..];
104106

105-
if (!string.IsNullOrEmpty(headerName.Value))
107+
if (!string.IsNullOrEmpty(headerValue))
106108
{
107-
int valueLength = Encoding.ASCII.GetBytes(headerName.Value, dataDestination);
109+
var valueLength = Encoding.ASCII.GetBytes(headerValue, dataDestination);
108110
fixed (byte* address = &MemoryMarshal.GetReference(dataDestination))
109111
{
110-
unknownHeaderStructure.pRawValue = address;
112+
unknownHeaderStructure.pRawValue = (PCSTR)address;
111113
unknownHeaderStructure.RawValueLength = (ushort)valueLength;
112114
}
113-
dataDestination = dataDestination.Slice(nameLength);
115+
dataDestination = dataDestination[nameLength..];
114116
}
115117
MemoryMarshal.Write(unknownHeaderStructureDestination, in unknownHeaderStructure);
116-
unknownHeaderStructureDestination = unknownHeaderStructureDestination.Slice(unknownHeadersSize);
118+
unknownHeaderStructureDestination = unknownHeaderStructureDestination[unknownHeadersSize..];
117119
}
118120
return dataDestination;
119121
}
120122

121-
private IReadOnlyCollection<(string, string)> GenerateUnknownHeaders(int count)
123+
private static List<(string, string)> GenerateUnknownHeaders(int count)
122124
{
123125
var result = new List<(string, string)>();
124-
for (int i = 0; i < count; i++)
126+
for (var i = 0; i < count; i++)
125127
{
126128
result.Add(($"X-Custom-{i}", $"Value-{i}"));
127129
}
Lines changed: 62 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,89 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System;
5-
using System.Net;
64
using System.Net.Http;
75
using System.Net.WebSockets;
86
using System.Text;
9-
using System.Threading;
10-
using System.Threading.Tasks;
117

12-
namespace TestClient
8+
namespace TestClient;
9+
10+
public class Program
1311
{
14-
public class Program
12+
private const string Address =
13+
"http://localhost:5000/public/1kb.txt";
14+
// "https://localhost:9090/public/1kb.txt";
15+
16+
public static void Main(string[] args)
1517
{
16-
private const string Address =
17-
"http://localhost:5000/public/1kb.txt";
18-
// "https://localhost:9090/public/1kb.txt";
18+
Console.WriteLine("Ready");
19+
Console.ReadKey();
1920

20-
public static void Main(string[] args)
21-
{
22-
Console.WriteLine("Ready");
23-
Console.ReadKey();
21+
var handler = new HttpClientHandler();
22+
handler.MaxConnectionsPerServer = 500;
23+
handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
24+
// handler.UseDefaultCredentials = true;
25+
HttpClient client = new HttpClient(handler);
2426

25-
var handler = new HttpClientHandler();
26-
handler.MaxConnectionsPerServer = 500;
27-
handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
28-
// handler.UseDefaultCredentials = true;
29-
HttpClient client = new HttpClient(handler);
27+
RunParallelRequests(client);
3028

31-
RunParallelRequests(client);
29+
// RunManualRequests(client);
3230

33-
// RunManualRequests(client);
31+
// RunWebSocketClient().Wait();
3432

35-
// RunWebSocketClient().Wait();
33+
Console.WriteLine("Done");
34+
// Console.ReadKey();
35+
}
3636

37-
Console.WriteLine("Done");
38-
// Console.ReadKey();
37+
private static void RunManualRequests(HttpClient client)
38+
{
39+
while (true)
40+
{
41+
Console.WriteLine("Press any key to send request");
42+
Console.ReadKey();
43+
var result = client.GetAsync(Address).Result;
44+
Console.WriteLine(result);
3945
}
46+
}
4047

41-
private static void RunManualRequests(HttpClient client)
48+
private static void RunParallelRequests(HttpClient client)
49+
{
50+
int completionCount = 0;
51+
int iterations = 100000;
52+
for (int i = 0; i < iterations; i++)
4253
{
43-
while (true)
44-
{
45-
Console.WriteLine("Press any key to send request");
46-
Console.ReadKey();
47-
var result = client.GetAsync(Address).Result;
48-
Console.WriteLine(result);
49-
}
54+
client.GetAsync(Address)
55+
.ContinueWith(t => Interlocked.Increment(ref completionCount));
5056
}
5157

52-
private static void RunParallelRequests(HttpClient client)
58+
while (completionCount < iterations)
5359
{
54-
int completionCount = 0;
55-
int iterations = 100000;
56-
for (int i = 0; i < iterations; i++)
57-
{
58-
client.GetAsync(Address)
59-
.ContinueWith(t => Interlocked.Increment(ref completionCount));
60-
}
61-
62-
while (completionCount < iterations)
63-
{
64-
Thread.Sleep(10);
65-
}
60+
Thread.Sleep(10);
6661
}
62+
}
63+
64+
public static async Task RunWebSocketClient()
65+
{
66+
ClientWebSocket websocket = new ClientWebSocket();
67+
68+
string url = "ws://localhost:5000/";
69+
Console.WriteLine("Connecting to: " + url);
70+
await websocket.ConnectAsync(new Uri(url), CancellationToken.None);
6771

68-
public static async Task RunWebSocketClient()
72+
string message = "Hello World";
73+
Console.WriteLine("Sending message: " + message);
74+
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
75+
await websocket.SendAsync(new ArraySegment<byte>(messageBytes), WebSocketMessageType.Text, true, CancellationToken.None);
76+
77+
byte[] incomingData = new byte[1024];
78+
WebSocketReceiveResult result = await websocket.ReceiveAsync(new ArraySegment<byte>(incomingData), CancellationToken.None);
79+
80+
if (result.CloseStatus.HasValue)
81+
{
82+
Console.WriteLine("Closed; Status: " + result.CloseStatus + ", " + result.CloseStatusDescription);
83+
}
84+
else
6985
{
70-
ClientWebSocket websocket = new ClientWebSocket();
71-
72-
string url = "ws://localhost:5000/";
73-
Console.WriteLine("Connecting to: " + url);
74-
await websocket.ConnectAsync(new Uri(url), CancellationToken.None);
75-
76-
string message = "Hello World";
77-
Console.WriteLine("Sending message: " + message);
78-
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
79-
await websocket.SendAsync(new ArraySegment<byte>(messageBytes), WebSocketMessageType.Text, true, CancellationToken.None);
80-
81-
byte[] incomingData = new byte[1024];
82-
WebSocketReceiveResult result = await websocket.ReceiveAsync(new ArraySegment<byte>(incomingData), CancellationToken.None);
83-
84-
if (result.CloseStatus.HasValue)
85-
{
86-
Console.WriteLine("Closed; Status: " + result.CloseStatus + ", " + result.CloseStatusDescription);
87-
}
88-
else
89-
{
90-
Console.WriteLine("Received message: " + Encoding.UTF8.GetString(incomingData, 0, result.Count));
91-
}
86+
Console.WriteLine("Received message: " + Encoding.UTF8.GetString(incomingData, 0, result.Count));
9287
}
9388
}
9489
}

src/Servers/HttpSys/src/AsyncAcceptContext.cs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
using System.Diagnostics;
55
using System.Threading.Tasks.Sources;
6-
using Microsoft.AspNetCore.HttpSys.Internal;
76

87
namespace Microsoft.AspNetCore.Server.HttpSys;
98

@@ -39,9 +38,9 @@ internal ValueTask<RequestContext> AcceptAsync()
3938

4039
AllocateNativeRequest();
4140

42-
uint statusCode = QueueBeginGetContext();
43-
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
44-
statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
41+
var statusCode = QueueBeginGetContext();
42+
if (statusCode != ErrorCodes.ERROR_SUCCESS &&
43+
statusCode != ErrorCodes.ERROR_IO_PENDING)
4544
{
4645
// some other bad error, possible(?) return values are:
4746
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
@@ -55,16 +54,16 @@ private void IOCompleted(uint errorCode, uint numBytes)
5554
{
5655
try
5756
{
58-
if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
59-
errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA)
57+
if (errorCode != ErrorCodes.ERROR_SUCCESS &&
58+
errorCode != ErrorCodes.ERROR_MORE_DATA)
6059
{
6160
_mrvts.SetException(new HttpSysException((int)errorCode));
6261
return;
6362
}
6463

6564
Debug.Assert(_requestContext != null);
6665

67-
if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
66+
if (errorCode == ErrorCodes.ERROR_SUCCESS)
6867
{
6968
var requestContext = _requestContext;
7069
// It's important that we clear the request context before we set the result
@@ -79,10 +78,10 @@ private void IOCompleted(uint errorCode, uint numBytes)
7978
AllocateNativeRequest(numBytes, _requestContext.RequestId);
8079

8180
// We need to issue a new request, either because auth failed, or because our buffer was too small the first time.
82-
uint statusCode = QueueBeginGetContext();
81+
var statusCode = QueueBeginGetContext();
8382

84-
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
85-
statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
83+
if (statusCode != ErrorCodes.ERROR_SUCCESS &&
84+
statusCode != ErrorCodes.ERROR_IO_PENDING)
8685
{
8786
// someother bad error, possible(?) return values are:
8887
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
@@ -117,14 +116,14 @@ private uint QueueBeginGetContext()
117116
_requestContext.RequestId,
118117
// Small perf impact by not using HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY
119118
// if the request sends header+body in a single TCP packet
120-
(uint)HttpApiTypes.HTTP_FLAGS.NONE,
119+
0u,
121120
_requestContext.NativeRequest,
122121
_requestContext.Size,
123122
&bytesTransferred,
124123
_overlapped);
125124

126-
if ((statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_CONNECTION_INVALID
127-
|| statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_INVALID_PARAMETER)
125+
if ((statusCode == ErrorCodes.ERROR_CONNECTION_INVALID
126+
|| statusCode == ErrorCodes.ERROR_INVALID_PARAMETER)
128127
&& _requestContext.RequestId != 0)
129128
{
130129
// ERROR_CONNECTION_INVALID:
@@ -139,15 +138,15 @@ private uint QueueBeginGetContext()
139138
_requestContext.RequestId = 0;
140139
retry = true;
141140
}
142-
else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA)
141+
else if (statusCode == ErrorCodes.ERROR_MORE_DATA)
143142
{
144143
// the buffer was not big enough to fit the headers, we need
145144
// to read the RequestId returned, allocate a new buffer of the required size
146145
// (uint)backingBuffer.Length - AlignmentPadding
147146
AllocateNativeRequest(bytesTransferred);
148147
retry = true;
149148
}
150-
else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS
149+
else if (statusCode == ErrorCodes.ERROR_SUCCESS
151150
&& HttpSysListener.SkipIOCPCallbackOnSuccess)
152151
{
153152
// IO operation completed synchronously - callback won't be called to signal completion.

0 commit comments

Comments
 (0)