private async Task <int> ReadAsyncCore(byte[] buffer, int offset, int count, CancellationToken token)
{
if (count == 0)
{
return(0);
}
_state.PinReceiveBuffer(buffer);
var ctr = token.Register(s => ((WinHttpResponseStream)s).CancelPendingResponseStreamReadOperation(), this);
_state.AsyncReadInProgress = true;
try
{
lock (_state.Lock)
{
Debug.Assert(!_requestHandle.IsInvalid);
if (!Interop.WinHttp.WinHttpQueryDataAvailable(_requestHandle, IntPtr.Zero))
{
throw new IOException(SR.net_http_io_read, WinHttpException.CreateExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpQueryDataAvailable)));
}
}
int bytesAvailable = await _state.LifecycleAwaitable;
lock (_state.Lock)
{
Debug.Assert(!_requestHandle.IsInvalid);
if (!Interop.WinHttp.WinHttpReadData(
_requestHandle,
Marshal.UnsafeAddrOfPinnedArrayElement(buffer, offset),
(uint)Math.Min(bytesAvailable, count),
IntPtr.Zero))
{
throw new IOException(SR.net_http_io_read, WinHttpException.CreateExceptionUsingLastError(nameof(Interop.WinHttp.WinHttpReadData)));
}
}
return(await _state.LifecycleAwaitable);
}
finally
{
_state.AsyncReadInProgress = false;
ctr.Dispose();
}
}