| File: Core\IO\WebSocketsAsyncIOEngine.Read.cs | Web Access |
| Project: src\aspnetcore\src\Servers\IIS\IIS\src\Microsoft.AspNetCore.Server.IIS.csproj (Microsoft.AspNetCore.Server.IIS) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers; using System.Diagnostics; using System.Runtime.InteropServices; namespace Microsoft.AspNetCore.Server.IIS.Core.IO; internal partial class WebSocketsAsyncIOEngine { internal sealed class WebSocketReadOperation : AsyncIOOperation, IDisposable { [UnmanagedCallersOnly] public static NativeMethods.REQUEST_NOTIFICATION_STATUS ReadCallback(IntPtr httpContext, IntPtr completionInfo, IntPtr completionContext) { var context = (WebSocketReadOperation)GCHandle.FromIntPtr(completionContext).Target!; NativeMethods.HttpGetCompletionInfo(completionInfo, out var cbBytes, out var hr); var continuation = context.Complete(hr, cbBytes); continuation.Invoke(); return NativeMethods.REQUEST_NOTIFICATION_STATUS.RQ_NOTIFICATION_PENDING; } private readonly WebSocketsAsyncIOEngine _engine; private readonly GCHandle _thisHandle; private MemoryHandle _inputHandle; private NativeSafeHandle? _requestHandler; private Memory<byte> _memory; public WebSocketReadOperation(WebSocketsAsyncIOEngine engine) { _thisHandle = GCHandle.Alloc(this); _engine = engine; } protected override unsafe bool InvokeOperation(out int hr, out int bytes) { Debug.Assert(_requestHandler != null, "Must initialize first."); _inputHandle = _memory.Pin(); hr = NativeMethods.HttpWebsocketsReadBytes( _requestHandler, (byte*)_inputHandle.Pointer, _memory.Length, &ReadCallback, (IntPtr)_thisHandle, out bytes, out var completionExpected); return !completionExpected; } public void Initialize(NativeSafeHandle requestHandler, Memory<byte> memory) { _requestHandler = requestHandler; _memory = memory; } public override void FreeOperationResources(int hr, int bytes) { _inputHandle.Dispose(); } protected override void ResetOperation() { base.ResetOperation(); _memory = default; _inputHandle.Dispose(); _inputHandle = default; _requestHandler = default; } protected override bool IsSuccessfulResult(int hr) => hr == NativeMethods.ERROR_HANDLE_EOF; public void Dispose() { _thisHandle.Free(); } } }