public override int Read([In, Out] byte[] buffer, int offset, int size)
{
if (NetEventSource.IsEnabled)
{
NetEventSource.Enter(this);
NetEventSource.Info(this, "size:" + size + " offset:" + offset);
}
if (buffer == null)
{
throw new ArgumentNullException(nameof(buffer));
}
if (offset < 0 || offset > buffer.Length)
{
throw new ArgumentOutOfRangeException(nameof(offset));
}
if (size < 0 || size > buffer.Length - offset)
{
throw new ArgumentOutOfRangeException(nameof(size));
}
if (size == 0 || _closed)
{
if (NetEventSource.IsEnabled) NetEventSource.Exit(this, "dataRead:0");
return 0;
}
uint dataRead = 0;
if (_dataChunkIndex != -1)
{
dataRead = Interop.HttpApi.GetChunks(_httpContext.Request.RequestBuffer, _httpContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size);
}
if (_dataChunkIndex == -1 && dataRead < size)
{
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "size:" + size + " offset:" + offset);
uint statusCode = 0;
uint extraDataRead = 0;
offset += (int)dataRead;
size -= (int)dataRead;
//the http.sys team recommends that we limit the size to 128kb
if (size > MaxReadSize)
{
size = MaxReadSize;
}
fixed (byte* pBuffer = buffer)
{
// issue unmanaged blocking call
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Calling Interop.HttpApi.HttpReceiveRequestEntityBody");
uint flags = 0;
if (!_inOpaqueMode)
{
flags = (uint)Interop.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY;
}
statusCode =
Interop.HttpApi.HttpReceiveRequestEntityBody(
_httpContext.RequestQueueHandle,
_httpContext.RequestId,
flags,
(void*)(pBuffer + offset),
(uint)size,
out extraDataRead,
null);
dataRead += extraDataRead;
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Call to Interop.HttpApi.HttpReceiveRequestEntityBody returned:" + statusCode + " dataRead:" + dataRead);
}
if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_HANDLE_EOF)
{
Exception exception = new HttpListenerException((int)statusCode);
if (NetEventSource.IsEnabled) NetEventSource.Error(this, exception.ToString());
throw exception;
}
UpdateAfterRead(statusCode, dataRead);
}
if (NetEventSource.IsEnabled)
{
NetEventSource.DumpBuffer(this, buffer, offset, (int)dataRead);
NetEventSource.Info(this, "returning dataRead:" + dataRead);
NetEventSource.Exit(this, "dataRead:" + dataRead);
}
return (int)dataRead;
}