Skip to content

Commit 6606d7c

Browse files
authored
Use function pointers for reverse pinvokes (#28249)
* Use function pointers for reverse pinvokes - Mostly a mechanical change to use function pointers
1 parent 47138f9 commit 6606d7c

File tree

5 files changed

+60
-60
lines changed

5 files changed

+60
-60
lines changed

src/Servers/IIS/IIS/src/Core/IISHttpServer.cs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using System.Threading.Tasks;
99
using Microsoft.AspNetCore.Authentication;
1010
using Microsoft.AspNetCore.Builder;
11-
using Microsoft.AspNetCore.Hosting;
1211
using Microsoft.AspNetCore.Hosting.Server;
1312
using Microsoft.AspNetCore.Hosting.Server.Features;
1413
using Microsoft.AspNetCore.Http.Features;
@@ -22,12 +21,6 @@ internal class IISHttpServer : IServer
2221
{
2322
private const string WebSocketVersionString = "WEBSOCKET_VERSION";
2423

25-
private static readonly NativeMethods.PFN_REQUEST_HANDLER _requestHandler = HandleRequest;
26-
private static readonly NativeMethods.PFN_SHUTDOWN_HANDLER _shutdownHandler = HandleShutdown;
27-
private static readonly NativeMethods.PFN_DISCONNECT_HANDLER _onDisconnect = OnDisconnect;
28-
private static readonly NativeMethods.PFN_ASYNC_COMPLETION _onAsyncCompletion = OnAsyncCompletion;
29-
private static readonly NativeMethods.PFN_REQUESTS_DRAINED_HANDLER _requestsDrainedHandler = OnRequestsDrained;
30-
3124
private IISContextFactory _iisContextFactory;
3225
private readonly MemoryPool<byte> _memoryPool = new SlabMemoryPool();
3326
private GCHandle _httpServerHandle;
@@ -89,12 +82,19 @@ ILogger<IISHttpServer> logger
8982
}
9083
}
9184

92-
public Task StartAsync<TContext>(IHttpApplication<TContext> application, CancellationToken cancellationToken)
85+
public unsafe Task StartAsync<TContext>(IHttpApplication<TContext> application, CancellationToken cancellationToken)
9386
{
9487
_httpServerHandle = GCHandle.Alloc(this);
9588

9689
_iisContextFactory = new IISContextFactory<TContext>(_memoryPool, application, _options, this, _logger);
97-
_nativeApplication.RegisterCallbacks(_requestHandler, _shutdownHandler, _onDisconnect, _onAsyncCompletion, _requestsDrainedHandler, (IntPtr)_httpServerHandle, (IntPtr)_httpServerHandle);
90+
_nativeApplication.RegisterCallbacks(
91+
&HandleRequest,
92+
&HandleShutdown,
93+
&OnDisconnect,
94+
&OnAsyncCompletion,
95+
&OnRequestsDrained,
96+
(IntPtr)_httpServerHandle,
97+
(IntPtr)_httpServerHandle);
9898

9999
_serverAddressesFeature.Addresses = _options.ServerAddresses;
100100

@@ -134,6 +134,7 @@ public void Dispose()
134134
_nativeApplication.Dispose();
135135
}
136136

137+
[UnmanagedCallersOnly]
137138
private static NativeMethods.REQUEST_NOTIFICATION_STATUS HandleRequest(IntPtr pInProcessHandler, IntPtr pvRequestContext)
138139
{
139140
IISHttpServer server = null;
@@ -163,7 +164,8 @@ private static NativeMethods.REQUEST_NOTIFICATION_STATUS HandleRequest(IntPtr pI
163164
}
164165
}
165166

166-
private static bool HandleShutdown(IntPtr pvRequestContext)
167+
[UnmanagedCallersOnly]
168+
private static int HandleShutdown(IntPtr pvRequestContext)
167169
{
168170
IISHttpServer server = null;
169171
try
@@ -174,7 +176,7 @@ private static bool HandleShutdown(IntPtr pvRequestContext)
174176
if (server == null)
175177
{
176178
// return value isn't checked.
177-
return true;
179+
return 1;
178180
}
179181

180182
server._applicationLifetime.StopApplication();
@@ -183,9 +185,10 @@ private static bool HandleShutdown(IntPtr pvRequestContext)
183185
{
184186
server?._logger.LogError(0, ex, $"Unexpected exception in {nameof(IISHttpServer)}.{nameof(HandleShutdown)}.");
185187
}
186-
return true;
188+
return 1;
187189
}
188190

191+
[UnmanagedCallersOnly]
189192
private static void OnDisconnect(IntPtr pvManagedHttpContext)
190193
{
191194
IISHttpContext context = null;
@@ -207,6 +210,7 @@ private static void OnDisconnect(IntPtr pvManagedHttpContext)
207210
}
208211
}
209212

213+
[UnmanagedCallersOnly]
210214
private static NativeMethods.REQUEST_NOTIFICATION_STATUS OnAsyncCompletion(IntPtr pvManagedHttpContext, int hr, int bytes)
211215
{
212216
IISHttpContext context = null;
@@ -231,6 +235,7 @@ private static NativeMethods.REQUEST_NOTIFICATION_STATUS OnAsyncCompletion(IntPt
231235
}
232236
}
233237

238+
[UnmanagedCallersOnly]
234239
private static void OnRequestsDrained(IntPtr serverContext)
235240
{
236241
IISHttpServer server = null;

src/Servers/IIS/IIS/src/Core/IISNativeApplication.cs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5-
using System.IO;
65

76
namespace Microsoft.AspNetCore.Server.IIS.Core
87
{
@@ -38,24 +37,24 @@ public void StopCallsIntoManaged()
3837
}
3938
}
4039

41-
public void RegisterCallbacks(
42-
NativeMethods.PFN_REQUEST_HANDLER requestHandler,
43-
NativeMethods.PFN_SHUTDOWN_HANDLER shutdownHandler,
44-
NativeMethods.PFN_DISCONNECT_HANDLER disconnectHandler,
45-
NativeMethods.PFN_ASYNC_COMPLETION onAsyncCompletion,
46-
NativeMethods.PFN_REQUESTS_DRAINED_HANDLER requestDrainedHandler,
47-
IntPtr requestContext,
48-
IntPtr shutdownContext)
40+
public unsafe void RegisterCallbacks(
41+
delegate* unmanaged<nint, nint, NativeMethods.REQUEST_NOTIFICATION_STATUS> requestCallback,
42+
delegate* unmanaged<nint, int> shutdownCallback,
43+
delegate* unmanaged<nint, void> disconnectCallback,
44+
delegate* unmanaged<nint, int, int, NativeMethods.REQUEST_NOTIFICATION_STATUS> asyncCallback,
45+
delegate* unmanaged<nint, void> requestsDrainedHandler,
46+
nint pvRequestContext,
47+
nint pvShutdownContext)
4948
{
5049
NativeMethods.HttpRegisterCallbacks(
5150
_nativeApplication,
52-
requestHandler,
53-
shutdownHandler,
54-
disconnectHandler,
55-
onAsyncCompletion,
56-
requestDrainedHandler,
57-
requestContext,
58-
shutdownContext);
51+
requestCallback,
52+
shutdownCallback,
53+
disconnectCallback,
54+
asyncCallback,
55+
requestsDrainedHandler,
56+
pvRequestContext,
57+
pvShutdownContext);
5958
}
6059

6160
public void Dispose()

src/Servers/IIS/IIS/src/Core/IO/WebSocketsAsyncIOEngine.Read.cs

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

44
using System;
55
using System.Buffers;
6+
using System.Runtime.CompilerServices;
67
using System.Runtime.InteropServices;
78

89
namespace Microsoft.AspNetCore.Server.IIS.Core.IO
@@ -11,7 +12,8 @@ internal partial class WebSocketsAsyncIOEngine
1112
{
1213
internal class WebSocketReadOperation : AsyncIOOperation
1314
{
14-
public static readonly NativeMethods.PFN_WEBSOCKET_ASYNC_COMPLETION ReadCallback = (httpContext, completionInfo, completionContext) =>
15+
[UnmanagedCallersOnly]
16+
public static NativeMethods.REQUEST_NOTIFICATION_STATUS ReadCallback(IntPtr httpContext, IntPtr completionInfo, IntPtr completionContext)
1517
{
1618
var context = (WebSocketReadOperation)GCHandle.FromIntPtr(completionContext).Target;
1719

@@ -22,7 +24,7 @@ internal class WebSocketReadOperation : AsyncIOOperation
2224
continuation.Invoke();
2325

2426
return NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_PENDING;
25-
};
27+
}
2628

2729
private readonly WebSocketsAsyncIOEngine _engine;
2830
private GCHandle _thisHandle;
@@ -44,7 +46,7 @@ protected override unsafe bool InvokeOperation(out int hr, out int bytes)
4446
_requestHandler,
4547
(byte*)_inputHandle.Pointer,
4648
_memory.Length,
47-
ReadCallback,
49+
&ReadCallback,
4850
(IntPtr)_thisHandle,
4951
out bytes,
5052
out var completionExpected);

src/Servers/IIS/IIS/src/Core/IO/WebSocketsAsyncIOEngine.Write.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5+
using System.Runtime.CompilerServices;
56
using System.Runtime.InteropServices;
67
using Microsoft.AspNetCore.HttpSys.Internal;
78

@@ -11,8 +12,8 @@ internal partial class WebSocketsAsyncIOEngine
1112
{
1213
internal sealed class WebSocketWriteOperation : AsyncWriteOperationBase
1314
{
14-
15-
private static readonly NativeMethods.PFN_WEBSOCKET_ASYNC_COMPLETION WriteCallback = (httpContext, completionInfo, completionContext) =>
15+
[UnmanagedCallersOnly]
16+
private static NativeMethods.REQUEST_NOTIFICATION_STATUS WriteCallback(IntPtr httpContext, IntPtr completionInfo, IntPtr completionContext)
1617
{
1718
var context = (WebSocketWriteOperation)GCHandle.FromIntPtr(completionContext).Target;
1819

@@ -22,7 +23,7 @@ internal sealed class WebSocketWriteOperation : AsyncWriteOperationBase
2223
continuation.Invoke();
2324

2425
return NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_PENDING;
25-
};
26+
}
2627

2728
private readonly WebSocketsAsyncIOEngine _engine;
2829
private GCHandle _thisHandle;
@@ -35,7 +36,7 @@ public WebSocketWriteOperation(WebSocketsAsyncIOEngine engine)
3536
protected override unsafe int WriteChunks(NativeSafeHandle requestHandler, int chunkCount, HttpApiTypes.HTTP_DATA_CHUNK* dataChunks, out bool completionExpected)
3637
{
3738
_thisHandle = GCHandle.Alloc(this);
38-
return NativeMethods.HttpWebsocketsWriteBytes(requestHandler, dataChunks, chunkCount, WriteCallback, (IntPtr)_thisHandle, out completionExpected);
39+
return NativeMethods.HttpWebsocketsWriteBytes(requestHandler, dataChunks, chunkCount, &WriteCallback, (IntPtr)_thisHandle, out completionExpected);
3940
}
4041

4142
protected override void ResetOperation()

src/Servers/IIS/IIS/src/NativeMethods.cs

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,6 @@ public enum REQUEST_NOTIFICATION_STATUS
3939
RQ_NOTIFICATION_FINISH_REQUEST
4040
}
4141

42-
public delegate REQUEST_NOTIFICATION_STATUS PFN_REQUEST_HANDLER(IntPtr pInProcessHandler, IntPtr pvRequestContext);
43-
public delegate void PFN_DISCONNECT_HANDLER(IntPtr pvManagedHttpContext);
44-
public delegate bool PFN_SHUTDOWN_HANDLER(IntPtr pvRequestContext);
45-
public delegate REQUEST_NOTIFICATION_STATUS PFN_ASYNC_COMPLETION(IntPtr pvManagedHttpContext, int hr, int bytes);
46-
public delegate REQUEST_NOTIFICATION_STATUS PFN_WEBSOCKET_ASYNC_COMPLETION(IntPtr pInProcessHandler, IntPtr completionInfo, IntPtr pvCompletionContext);
47-
public delegate void PFN_REQUESTS_DRAINED_HANDLER(IntPtr pvRequestContext);
48-
4942
[DllImport(AspNetCoreModuleDll)]
5043
private static extern int http_post_completion(NativeSafeHandle pInProcessHandler, int cbBytes);
5144

@@ -56,12 +49,12 @@ public enum REQUEST_NOTIFICATION_STATUS
5649
private static extern void http_indicate_completion(NativeSafeHandle pInProcessHandler, REQUEST_NOTIFICATION_STATUS notificationStatus);
5750

5851
[DllImport(AspNetCoreModuleDll)]
59-
private static extern int register_callbacks(NativeSafeHandle pInProcessApplication,
60-
PFN_REQUEST_HANDLER requestCallback,
61-
PFN_SHUTDOWN_HANDLER shutdownCallback,
62-
PFN_DISCONNECT_HANDLER disconnectCallback,
63-
PFN_ASYNC_COMPLETION asyncCallback,
64-
PFN_REQUESTS_DRAINED_HANDLER requestsDrainedHandler,
52+
private unsafe static extern int register_callbacks(NativeSafeHandle pInProcessApplication,
53+
delegate* unmanaged<IntPtr, IntPtr, REQUEST_NOTIFICATION_STATUS> requestCallback,
54+
delegate* unmanaged<IntPtr, int> shutdownCallback,
55+
delegate* unmanaged<IntPtr, void> disconnectCallback,
56+
delegate* unmanaged<IntPtr, int, int, REQUEST_NOTIFICATION_STATUS> asyncCallback,
57+
delegate* unmanaged<IntPtr, void> requestsDrainedHandler,
6558
IntPtr pvRequestContext,
6659
IntPtr pvShutdownContext);
6760

@@ -115,7 +108,7 @@ private static extern unsafe int http_websockets_read_bytes(
115108
NativeSafeHandle pInProcessHandler,
116109
byte* pvBuffer,
117110
int cbBuffer,
118-
PFN_WEBSOCKET_ASYNC_COMPLETION pfnCompletionCallback,
111+
delegate* unmanaged<IntPtr, IntPtr, IntPtr, REQUEST_NOTIFICATION_STATUS> pfnCompletionCallback,
119112
IntPtr pvCompletionContext,
120113
out int dwBytesReceived,
121114
out bool fCompletionExpected);
@@ -125,7 +118,7 @@ private static extern unsafe int http_websockets_write_bytes(
125118
NativeSafeHandle pInProcessHandler,
126119
HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks,
127120
int nChunks,
128-
PFN_WEBSOCKET_ASYNC_COMPLETION pfnCompletionCallback,
121+
delegate* unmanaged<IntPtr, IntPtr, IntPtr, REQUEST_NOTIFICATION_STATUS> pfnCompletionCallback,
129122
IntPtr pvCompletionContext,
130123
out bool fCompletionExpected);
131124

@@ -168,12 +161,12 @@ public static void HttpSetCompletionStatus(NativeSafeHandle pInProcessHandler, R
168161
Validate(http_set_completion_status(pInProcessHandler, rquestNotificationStatus));
169162
}
170163

171-
public static void HttpRegisterCallbacks(NativeSafeHandle pInProcessApplication,
172-
PFN_REQUEST_HANDLER requestCallback,
173-
PFN_SHUTDOWN_HANDLER shutdownCallback,
174-
PFN_DISCONNECT_HANDLER disconnectCallback,
175-
PFN_ASYNC_COMPLETION asyncCallback,
176-
PFN_REQUESTS_DRAINED_HANDLER requestsDrainedHandler,
164+
public static unsafe void HttpRegisterCallbacks(NativeSafeHandle pInProcessApplication,
165+
delegate* unmanaged<IntPtr, IntPtr, REQUEST_NOTIFICATION_STATUS> requestCallback,
166+
delegate* unmanaged<IntPtr, int> shutdownCallback,
167+
delegate* unmanaged<IntPtr, void> disconnectCallback,
168+
delegate* unmanaged<IntPtr, int, int, REQUEST_NOTIFICATION_STATUS> asyncCallback,
169+
delegate* unmanaged<IntPtr, void> requestsDrainedHandler,
177170
IntPtr pvRequestContext,
178171
IntPtr pvShutdownContext)
179172
{
@@ -251,7 +244,7 @@ public static unsafe int HttpWebsocketsReadBytes(
251244
NativeSafeHandle pInProcessHandler,
252245
byte* pvBuffer,
253246
int cbBuffer,
254-
PFN_WEBSOCKET_ASYNC_COMPLETION pfnCompletionCallback,
247+
delegate* unmanaged<IntPtr, IntPtr, IntPtr, REQUEST_NOTIFICATION_STATUS> pfnCompletionCallback,
255248
IntPtr pvCompletionContext, out int dwBytesReceived,
256249
out bool fCompletionExpected)
257250
{
@@ -262,7 +255,7 @@ internal static unsafe int HttpWebsocketsWriteBytes(
262255
NativeSafeHandle pInProcessHandler,
263256
HttpApiTypes.HTTP_DATA_CHUNK* pDataChunks,
264257
int nChunks,
265-
PFN_WEBSOCKET_ASYNC_COMPLETION pfnCompletionCallback,
258+
delegate* unmanaged<IntPtr, IntPtr, IntPtr, REQUEST_NOTIFICATION_STATUS> pfnCompletionCallback,
266259
IntPtr pvCompletionContext,
267260
out bool fCompletionExpected)
268261
{
@@ -280,7 +273,7 @@ public static bool HttpTryCancelIO(NativeSafeHandle pInProcessHandler)
280273
// ERROR_NOT_FOUND is expected if async operation finished
281274
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa363792(v=vs.85).aspx
282275
// ERROR_INVALID_PARAMETER is expected for "fake" requests like applicationInitialization ones
283-
if (hr == ERROR_NOT_FOUND || hr == ERROR_INVALID_PARAMETER)
276+
if (hr == ERROR_NOT_FOUND || hr == ERROR_INVALID_PARAMETER)
284277
{
285278
return false;
286279
}
@@ -310,7 +303,7 @@ public static void HttpGetAuthenticationInformation(NativeSafeHandle pInProcessH
310303

311304
internal static unsafe void HttpSetStartupErrorPageContent(byte[] content)
312305
{
313-
fixed(byte* bytePtr = content)
306+
fixed (byte* bytePtr = content)
314307
{
315308
http_set_startup_error_page_content(bytePtr, content.Length);
316309
}

0 commit comments

Comments
 (0)