parent
10df99de67
commit
f63e53b597
|
|
@ -1049,12 +1049,13 @@ namespace Microsoft.Net.Http.Server
|
|||
|
||||
// Server API
|
||||
|
||||
internal static void GetUnknownHeaders(IDictionary<string, StringValues> unknownHeaders, byte[] memoryBlob, IntPtr originalAddress)
|
||||
internal static void GetUnknownHeaders(IDictionary<string, StringValues> unknownHeaders, byte[] memoryBlob,
|
||||
int requestOffset, IntPtr originalAddress)
|
||||
{
|
||||
// Return value.
|
||||
fixed (byte* pMemoryBlob = memoryBlob)
|
||||
{
|
||||
HTTP_REQUEST* request = (HTTP_REQUEST*)pMemoryBlob;
|
||||
HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset);
|
||||
long fixup = pMemoryBlob - (byte*)originalAddress;
|
||||
int index;
|
||||
|
||||
|
|
@ -1064,7 +1065,7 @@ namespace Microsoft.Net.Http.Server
|
|||
HTTP_UNKNOWN_HEADER* pUnknownHeader = (HTTP_UNKNOWN_HEADER*)(fixup + (byte*)request->Headers.pUnknownHeaders);
|
||||
for (index = 0; index < request->Headers.UnknownHeaderCount; index++)
|
||||
{
|
||||
// For unknown headers, when header value is empty, RawValueLength will be 0 and
|
||||
// For unknown headers, when header value is empty, RawValueLength will be 0 and
|
||||
// pRawValue will be null.
|
||||
if (pUnknownHeader->pName != null && pUnknownHeader->NameLength > 0)
|
||||
{
|
||||
|
|
@ -1093,7 +1094,7 @@ namespace Microsoft.Net.Http.Server
|
|||
string header = null;
|
||||
|
||||
HTTP_KNOWN_HEADER* pKnownHeader = (&request->Headers.KnownHeaders) + headerIndex;
|
||||
// For known headers, when header value is empty, RawValueLength will be 0 and
|
||||
// For known headers, when header value is empty, RawValueLength will be 0 and
|
||||
// pRawValue will point to empty string ("\0")
|
||||
if (pKnownHeader->pRawValue != null)
|
||||
{
|
||||
|
|
@ -1103,11 +1104,12 @@ namespace Microsoft.Net.Http.Server
|
|||
return header;
|
||||
}
|
||||
|
||||
internal static string GetKnownHeader(byte[] memoryBlob, IntPtr originalAddress, int headerIndex)
|
||||
internal static string GetKnownHeader(byte[] memoryBlob, int requestOffset, IntPtr originalAddress, int headerIndex)
|
||||
{
|
||||
fixed (byte* pMemoryBlob = memoryBlob)
|
||||
{
|
||||
return GetKnownHeader((HTTP_REQUEST*)pMemoryBlob, pMemoryBlob - (byte*)originalAddress, headerIndex);
|
||||
return GetKnownHeader(
|
||||
(HTTP_REQUEST*)(pMemoryBlob + requestOffset), pMemoryBlob - (byte*)originalAddress, headerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1127,21 +1129,21 @@ namespace Microsoft.Net.Http.Server
|
|||
return verb;
|
||||
}
|
||||
|
||||
internal static unsafe string GetVerb(byte[] memoryBlob, IntPtr originalAddress)
|
||||
internal static unsafe string GetVerb(byte[] memoryBlob, int requestOffset, IntPtr originalAddress)
|
||||
{
|
||||
fixed (byte* pMemoryBlob = memoryBlob)
|
||||
{
|
||||
return GetVerb((HTTP_REQUEST*)pMemoryBlob, pMemoryBlob - (byte*)originalAddress);
|
||||
return GetVerb((HTTP_REQUEST*)(pMemoryBlob + requestOffset), pMemoryBlob - (byte*)originalAddress);
|
||||
}
|
||||
}
|
||||
|
||||
internal static HTTP_VERB GetKnownVerb(byte[] memoryBlob, IntPtr originalAddress)
|
||||
internal static HTTP_VERB GetKnownVerb(byte[] memoryBlob, int requestOffset, IntPtr originalAddress)
|
||||
{
|
||||
// Return value.
|
||||
HTTP_VERB verb = HTTP_VERB.HttpVerbUnknown;
|
||||
fixed (byte* pMemoryBlob = memoryBlob)
|
||||
{
|
||||
HTTP_REQUEST* request = (HTTP_REQUEST*)pMemoryBlob;
|
||||
HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset);
|
||||
if ((int)request->Verb > (int)HTTP_VERB.HttpVerbUnparsed && (int)request->Verb < (int)HTTP_VERB.HttpVerbMaximum)
|
||||
{
|
||||
verb = request->Verb;
|
||||
|
|
@ -1151,13 +1153,14 @@ namespace Microsoft.Net.Http.Server
|
|||
return verb;
|
||||
}
|
||||
|
||||
internal static uint GetChunks(byte[] memoryBlob, IntPtr originalAddress, ref int dataChunkIndex, ref uint dataChunkOffset, byte[] buffer, int offset, int size)
|
||||
internal static uint GetChunks(byte[] memoryBlob, int requestOffset, IntPtr originalAddress,
|
||||
ref int dataChunkIndex, ref uint dataChunkOffset, byte[] buffer, int offset, int size)
|
||||
{
|
||||
// Return value.
|
||||
uint dataRead = 0;
|
||||
fixed (byte* pMemoryBlob = memoryBlob)
|
||||
{
|
||||
HTTP_REQUEST* request = (HTTP_REQUEST*)pMemoryBlob;
|
||||
HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset);
|
||||
long fixup = pMemoryBlob - (byte*)originalAddress;
|
||||
|
||||
if (request->EntityChunkCount > 0 && dataChunkIndex < request->EntityChunkCount && dataChunkIndex != -1)
|
||||
|
|
@ -1205,30 +1208,30 @@ namespace Microsoft.Net.Http.Server
|
|||
return dataRead;
|
||||
}
|
||||
|
||||
internal static SocketAddress GetRemoteEndPoint(byte[] memoryBlob, IntPtr originalAddress)
|
||||
internal static SocketAddress GetRemoteEndPoint(byte[] memoryBlob, int requestOffset, IntPtr originalAddress)
|
||||
{
|
||||
fixed (byte* pMemoryBlob = memoryBlob)
|
||||
{
|
||||
HTTP_REQUEST* request = (HTTP_REQUEST*)pMemoryBlob;
|
||||
return GetEndPoint(memoryBlob, originalAddress, (byte*)request->Address.pRemoteAddress);
|
||||
HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset);
|
||||
return GetEndPoint(memoryBlob, requestOffset, originalAddress, (byte*)request->Address.pRemoteAddress);
|
||||
}
|
||||
}
|
||||
|
||||
internal static SocketAddress GetLocalEndPoint(byte[] memoryBlob, IntPtr originalAddress)
|
||||
internal static SocketAddress GetLocalEndPoint(byte[] memoryBlob, int requestOffset, IntPtr originalAddress)
|
||||
{
|
||||
fixed (byte* pMemoryBlob = memoryBlob)
|
||||
{
|
||||
HTTP_REQUEST* request = (HTTP_REQUEST*)pMemoryBlob;
|
||||
return GetEndPoint(memoryBlob, originalAddress, (byte*)request->Address.pLocalAddress);
|
||||
HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset);
|
||||
return GetEndPoint(memoryBlob, requestOffset, originalAddress, (byte*)request->Address.pLocalAddress);
|
||||
}
|
||||
}
|
||||
|
||||
internal static SocketAddress GetEndPoint(byte[] memoryBlob, IntPtr originalAddress, byte* source)
|
||||
internal static SocketAddress GetEndPoint(byte[] memoryBlob, int requestOffset, IntPtr originalAddress, byte* source)
|
||||
{
|
||||
fixed (byte* pMemoryBlob = memoryBlob)
|
||||
{
|
||||
IntPtr address = source != null ?
|
||||
(IntPtr)(pMemoryBlob - (byte*)originalAddress + source) : IntPtr.Zero;
|
||||
(IntPtr)(pMemoryBlob + requestOffset - (byte*)originalAddress + source) : IntPtr.Zero;
|
||||
return CopyOutAddress(address);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,9 +31,11 @@ namespace Microsoft.Net.Http.Server
|
|||
internal unsafe class NativeRequestContext : IDisposable
|
||||
{
|
||||
private const int DefaultBufferSize = 4096;
|
||||
private const int AlignmentPadding = 8;
|
||||
private UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST* _memoryBlob;
|
||||
private IntPtr _originalBlobAddress;
|
||||
private byte[] _backingBuffer;
|
||||
private int _bufferAlignment;
|
||||
private SafeNativeOverlapped _nativeOverlapped;
|
||||
private AsyncAcceptContext _acceptResult;
|
||||
|
||||
|
|
@ -80,7 +82,15 @@ namespace Microsoft.Net.Http.Server
|
|||
{
|
||||
get
|
||||
{
|
||||
return (uint)_backingBuffer.Length;
|
||||
return (uint)_backingBuffer.Length - AlignmentPadding;
|
||||
}
|
||||
}
|
||||
|
||||
internal int BufferAlignment
|
||||
{
|
||||
get
|
||||
{
|
||||
return _bufferAlignment;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +99,7 @@ namespace Microsoft.Net.Http.Server
|
|||
get
|
||||
{
|
||||
UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST* blob = _memoryBlob;
|
||||
return (blob == null ? _originalBlobAddress : (IntPtr)blob);
|
||||
return blob == null ? _originalBlobAddress : (IntPtr)blob;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -155,12 +165,13 @@ namespace Microsoft.Net.Http.Server
|
|||
|
||||
private void SetBuffer(int size)
|
||||
{
|
||||
_backingBuffer = size == 0 ? null : new byte[size];
|
||||
Debug.Assert(size != 0, "unexpected size");
|
||||
|
||||
_backingBuffer = new byte[size + AlignmentPadding];
|
||||
}
|
||||
|
||||
private UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST* Allocate(uint size)
|
||||
{
|
||||
uint newSize = size != 0 ? size : RequestBuffer == null ? DefaultBufferSize : Size;
|
||||
// We can't reuse overlapped objects
|
||||
if (_nativeOverlapped != null)
|
||||
{
|
||||
|
|
@ -168,15 +179,19 @@ namespace Microsoft.Net.Http.Server
|
|||
_nativeOverlapped = null;
|
||||
nativeOverlapped.Dispose();
|
||||
}
|
||||
if (_nativeOverlapped == null)
|
||||
{
|
||||
SetBuffer(checked((int)newSize));
|
||||
var boundHandle = _acceptResult.Server.BoundHandle;
|
||||
_nativeOverlapped = new SafeNativeOverlapped(boundHandle,
|
||||
boundHandle.AllocateNativeOverlapped(AsyncAcceptContext.IOCallback, _acceptResult, RequestBuffer));
|
||||
return (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST*)Marshal.UnsafeAddrOfPinnedArrayElement(RequestBuffer, 0);
|
||||
}
|
||||
return RequestBlob;
|
||||
|
||||
uint newSize = size != 0 ? size : RequestBuffer == null ? DefaultBufferSize : Size;
|
||||
SetBuffer(checked((int)newSize));
|
||||
var boundHandle = _acceptResult.Server.BoundHandle;
|
||||
_nativeOverlapped = new SafeNativeOverlapped(boundHandle,
|
||||
boundHandle.AllocateNativeOverlapped(AsyncAcceptContext.IOCallback, _acceptResult, RequestBuffer));
|
||||
|
||||
// HttpReceiveHttpRequest expects the request pointer to be 8-byte-aligned or it fails. On ARM
|
||||
// CLR creates buffers that are 4-byte-aligned so we need force 8-byte alignment.
|
||||
var requestAddress = Marshal.UnsafeAddrOfPinnedArrayElement(RequestBuffer, 0);
|
||||
_bufferAlignment = (int)(requestAddress.ToInt64() & 0x07);
|
||||
|
||||
return (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST*)(requestAddress + _bufferAlignment);
|
||||
}
|
||||
|
||||
internal void Reset(ulong requestId, uint size)
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ namespace Microsoft.Net.Http.Server
|
|||
_httpVersion = new Version(major, minor);
|
||||
}
|
||||
|
||||
_httpMethod = UnsafeNclNativeMethods.HttpApi.GetVerb(RequestBuffer, OriginalBlobAddress);
|
||||
_httpMethod = UnsafeNclNativeMethods.HttpApi.GetVerb(RequestBuffer, BufferAlignment, OriginalBlobAddress);
|
||||
_headers = new HeaderCollection(new RequestHeaders(_nativeRequestContext));
|
||||
|
||||
var requestV2 = (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_V2*)memoryBlob.RequestBlob;
|
||||
|
|
@ -190,6 +190,15 @@ namespace Microsoft.Net.Http.Server
|
|||
}
|
||||
}
|
||||
|
||||
internal int BufferAlignment
|
||||
{
|
||||
get
|
||||
{
|
||||
CheckDisposed();
|
||||
return _nativeRequestContext.BufferAlignment;
|
||||
}
|
||||
}
|
||||
|
||||
internal IntPtr OriginalBlobAddress
|
||||
{
|
||||
get
|
||||
|
|
@ -304,7 +313,7 @@ namespace Microsoft.Net.Http.Server
|
|||
return _rawUrl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Version ProtocolVersion
|
||||
{
|
||||
get
|
||||
|
|
@ -329,7 +338,7 @@ namespace Microsoft.Net.Http.Server
|
|||
{
|
||||
if (_remoteEndPoint == null)
|
||||
{
|
||||
_remoteEndPoint = UnsafeNclNativeMethods.HttpApi.GetRemoteEndPoint(RequestBuffer, OriginalBlobAddress);
|
||||
_remoteEndPoint = UnsafeNclNativeMethods.HttpApi.GetRemoteEndPoint(RequestBuffer, BufferAlignment, OriginalBlobAddress);
|
||||
}
|
||||
|
||||
return _remoteEndPoint;
|
||||
|
|
@ -342,7 +351,7 @@ namespace Microsoft.Net.Http.Server
|
|||
{
|
||||
if (_localEndPoint == null)
|
||||
{
|
||||
_localEndPoint = UnsafeNclNativeMethods.HttpApi.GetLocalEndPoint(RequestBuffer, OriginalBlobAddress);
|
||||
_localEndPoint = UnsafeNclNativeMethods.HttpApi.GetLocalEndPoint(RequestBuffer, BufferAlignment, OriginalBlobAddress);
|
||||
}
|
||||
|
||||
return _localEndPoint;
|
||||
|
|
@ -406,7 +415,7 @@ namespace Microsoft.Net.Http.Server
|
|||
|
||||
internal UnsafeNclNativeMethods.HttpApi.HTTP_VERB GetKnownMethod()
|
||||
{
|
||||
return UnsafeNclNativeMethods.HttpApi.GetKnownVerb(RequestBuffer, OriginalBlobAddress);
|
||||
return UnsafeNclNativeMethods.HttpApi.GetKnownVerb(RequestBuffer, BufferAlignment, OriginalBlobAddress);
|
||||
}
|
||||
|
||||
// Populates the client certificate. The result may be null if there is no client cert.
|
||||
|
|
|
|||
|
|
@ -86,13 +86,13 @@ namespace Microsoft.Net.Http.Server
|
|||
private string GetKnownHeader(HttpSysRequestHeader header)
|
||||
{
|
||||
return UnsafeNclNativeMethods.HttpApi.GetKnownHeader(_requestMemoryBlob.RequestBuffer,
|
||||
_requestMemoryBlob.OriginalBlobAddress, (int)header);
|
||||
_requestMemoryBlob.BufferAlignment, _requestMemoryBlob.OriginalBlobAddress, (int)header);
|
||||
}
|
||||
|
||||
private void GetUnknownHeaders(IDictionary<string, StringValues> extra)
|
||||
{
|
||||
UnsafeNclNativeMethods.HttpApi.GetUnknownHeaders(extra, _requestMemoryBlob.RequestBuffer,
|
||||
_requestMemoryBlob.OriginalBlobAddress);
|
||||
_requestMemoryBlob.BufferAlignment, _requestMemoryBlob.OriginalBlobAddress);
|
||||
}
|
||||
|
||||
void IDictionary<string, StringValues>.Add(string key, StringValues value)
|
||||
|
|
|
|||
|
|
@ -147,7 +147,9 @@ namespace Microsoft.Net.Http.Server
|
|||
|
||||
if (_dataChunkIndex != -1)
|
||||
{
|
||||
dataRead = UnsafeNclNativeMethods.HttpApi.GetChunks(_requestContext.Request.RequestBuffer, _requestContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size);
|
||||
dataRead = UnsafeNclNativeMethods.HttpApi.GetChunks(_requestContext.Request.RequestBuffer,
|
||||
_requestContext.Request.BufferAlignment, _requestContext.Request.OriginalBlobAddress,
|
||||
ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size);
|
||||
}
|
||||
|
||||
if (_dataChunkIndex == -1 && dataRead < size)
|
||||
|
|
@ -223,7 +225,9 @@ namespace Microsoft.Net.Http.Server
|
|||
uint dataRead = 0;
|
||||
if (_dataChunkIndex != -1)
|
||||
{
|
||||
dataRead = UnsafeNclNativeMethods.HttpApi.GetChunks(_requestContext.Request.RequestBuffer, _requestContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size);
|
||||
dataRead = UnsafeNclNativeMethods.HttpApi.GetChunks(_requestContext.Request.RequestBuffer, _requestContext.Request.BufferAlignment,
|
||||
_requestContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size);
|
||||
|
||||
if (_dataChunkIndex != -1 && dataRead == size)
|
||||
{
|
||||
asyncResult = new RequestStreamAsyncResult(this, state, callback, buffer, offset, 0);
|
||||
|
|
@ -339,7 +343,8 @@ namespace Microsoft.Net.Http.Server
|
|||
uint dataRead = 0;
|
||||
if (_dataChunkIndex != -1)
|
||||
{
|
||||
dataRead = UnsafeNclNativeMethods.HttpApi.GetChunks(_requestContext.Request.RequestBuffer, _requestContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size);
|
||||
dataRead = UnsafeNclNativeMethods.HttpApi.GetChunks(_requestContext.Request.RequestBuffer, _requestContext.Request.BufferAlignment,
|
||||
_requestContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size);
|
||||
if (_dataChunkIndex != -1 && dataRead == size)
|
||||
{
|
||||
UpdateAfterRead(UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS, dataRead);
|
||||
|
|
@ -347,7 +352,7 @@ namespace Microsoft.Net.Http.Server
|
|||
return Task.FromResult<int>((int)dataRead);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (_dataChunkIndex == -1 && dataRead < size)
|
||||
{
|
||||
uint statusCode = 0;
|
||||
|
|
|
|||
|
|
@ -890,7 +890,7 @@ namespace Microsoft.Net.Http.Server
|
|||
blob = new byte[size];
|
||||
fixed (byte* blobPtr = blob)
|
||||
{
|
||||
// Http.sys team: ServiceName will always be null if
|
||||
// Http.sys team: ServiceName will always be null if
|
||||
// HTTP_RECEIVE_SECURE_CHANNEL_TOKEN flag is set.
|
||||
statusCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate(
|
||||
RequestQueueHandle,
|
||||
|
|
|
|||
Loading…
Reference in New Issue