parent
10df99de67
commit
f63e53b597
|
|
@ -1049,12 +1049,13 @@ namespace Microsoft.Net.Http.Server
|
||||||
|
|
||||||
// Server API
|
// 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.
|
// Return value.
|
||||||
fixed (byte* pMemoryBlob = memoryBlob)
|
fixed (byte* pMemoryBlob = memoryBlob)
|
||||||
{
|
{
|
||||||
HTTP_REQUEST* request = (HTTP_REQUEST*)pMemoryBlob;
|
HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset);
|
||||||
long fixup = pMemoryBlob - (byte*)originalAddress;
|
long fixup = pMemoryBlob - (byte*)originalAddress;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
|
|
@ -1103,11 +1104,12 @@ namespace Microsoft.Net.Http.Server
|
||||||
return header;
|
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)
|
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;
|
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)
|
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.
|
// Return value.
|
||||||
HTTP_VERB verb = HTTP_VERB.HttpVerbUnknown;
|
HTTP_VERB verb = HTTP_VERB.HttpVerbUnknown;
|
||||||
fixed (byte* pMemoryBlob = memoryBlob)
|
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)
|
if ((int)request->Verb > (int)HTTP_VERB.HttpVerbUnparsed && (int)request->Verb < (int)HTTP_VERB.HttpVerbMaximum)
|
||||||
{
|
{
|
||||||
verb = request->Verb;
|
verb = request->Verb;
|
||||||
|
|
@ -1151,13 +1153,14 @@ namespace Microsoft.Net.Http.Server
|
||||||
return verb;
|
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.
|
// Return value.
|
||||||
uint dataRead = 0;
|
uint dataRead = 0;
|
||||||
fixed (byte* pMemoryBlob = memoryBlob)
|
fixed (byte* pMemoryBlob = memoryBlob)
|
||||||
{
|
{
|
||||||
HTTP_REQUEST* request = (HTTP_REQUEST*)pMemoryBlob;
|
HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset);
|
||||||
long fixup = pMemoryBlob - (byte*)originalAddress;
|
long fixup = pMemoryBlob - (byte*)originalAddress;
|
||||||
|
|
||||||
if (request->EntityChunkCount > 0 && dataChunkIndex < request->EntityChunkCount && dataChunkIndex != -1)
|
if (request->EntityChunkCount > 0 && dataChunkIndex < request->EntityChunkCount && dataChunkIndex != -1)
|
||||||
|
|
@ -1205,30 +1208,30 @@ namespace Microsoft.Net.Http.Server
|
||||||
return dataRead;
|
return dataRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static SocketAddress GetRemoteEndPoint(byte[] memoryBlob, IntPtr originalAddress)
|
internal static SocketAddress GetRemoteEndPoint(byte[] memoryBlob, int requestOffset, IntPtr originalAddress)
|
||||||
{
|
{
|
||||||
fixed (byte* pMemoryBlob = memoryBlob)
|
fixed (byte* pMemoryBlob = memoryBlob)
|
||||||
{
|
{
|
||||||
HTTP_REQUEST* request = (HTTP_REQUEST*)pMemoryBlob;
|
HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset);
|
||||||
return GetEndPoint(memoryBlob, originalAddress, (byte*)request->Address.pRemoteAddress);
|
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)
|
fixed (byte* pMemoryBlob = memoryBlob)
|
||||||
{
|
{
|
||||||
HTTP_REQUEST* request = (HTTP_REQUEST*)pMemoryBlob;
|
HTTP_REQUEST* request = (HTTP_REQUEST*)(pMemoryBlob + requestOffset);
|
||||||
return GetEndPoint(memoryBlob, originalAddress, (byte*)request->Address.pLocalAddress);
|
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)
|
fixed (byte* pMemoryBlob = memoryBlob)
|
||||||
{
|
{
|
||||||
IntPtr address = source != null ?
|
IntPtr address = source != null ?
|
||||||
(IntPtr)(pMemoryBlob - (byte*)originalAddress + source) : IntPtr.Zero;
|
(IntPtr)(pMemoryBlob + requestOffset - (byte*)originalAddress + source) : IntPtr.Zero;
|
||||||
return CopyOutAddress(address);
|
return CopyOutAddress(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,11 @@ namespace Microsoft.Net.Http.Server
|
||||||
internal unsafe class NativeRequestContext : IDisposable
|
internal unsafe class NativeRequestContext : IDisposable
|
||||||
{
|
{
|
||||||
private const int DefaultBufferSize = 4096;
|
private const int DefaultBufferSize = 4096;
|
||||||
|
private const int AlignmentPadding = 8;
|
||||||
private UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST* _memoryBlob;
|
private UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST* _memoryBlob;
|
||||||
private IntPtr _originalBlobAddress;
|
private IntPtr _originalBlobAddress;
|
||||||
private byte[] _backingBuffer;
|
private byte[] _backingBuffer;
|
||||||
|
private int _bufferAlignment;
|
||||||
private SafeNativeOverlapped _nativeOverlapped;
|
private SafeNativeOverlapped _nativeOverlapped;
|
||||||
private AsyncAcceptContext _acceptResult;
|
private AsyncAcceptContext _acceptResult;
|
||||||
|
|
||||||
|
|
@ -80,7 +82,15 @@ namespace Microsoft.Net.Http.Server
|
||||||
{
|
{
|
||||||
get
|
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
|
get
|
||||||
{
|
{
|
||||||
UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST* blob = _memoryBlob;
|
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)
|
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)
|
private UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST* Allocate(uint size)
|
||||||
{
|
{
|
||||||
uint newSize = size != 0 ? size : RequestBuffer == null ? DefaultBufferSize : Size;
|
|
||||||
// We can't reuse overlapped objects
|
// We can't reuse overlapped objects
|
||||||
if (_nativeOverlapped != null)
|
if (_nativeOverlapped != null)
|
||||||
{
|
{
|
||||||
|
|
@ -168,15 +179,19 @@ namespace Microsoft.Net.Http.Server
|
||||||
_nativeOverlapped = null;
|
_nativeOverlapped = null;
|
||||||
nativeOverlapped.Dispose();
|
nativeOverlapped.Dispose();
|
||||||
}
|
}
|
||||||
if (_nativeOverlapped == null)
|
|
||||||
{
|
uint newSize = size != 0 ? size : RequestBuffer == null ? DefaultBufferSize : Size;
|
||||||
SetBuffer(checked((int)newSize));
|
SetBuffer(checked((int)newSize));
|
||||||
var boundHandle = _acceptResult.Server.BoundHandle;
|
var boundHandle = _acceptResult.Server.BoundHandle;
|
||||||
_nativeOverlapped = new SafeNativeOverlapped(boundHandle,
|
_nativeOverlapped = new SafeNativeOverlapped(boundHandle,
|
||||||
boundHandle.AllocateNativeOverlapped(AsyncAcceptContext.IOCallback, _acceptResult, RequestBuffer));
|
boundHandle.AllocateNativeOverlapped(AsyncAcceptContext.IOCallback, _acceptResult, RequestBuffer));
|
||||||
return (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST*)Marshal.UnsafeAddrOfPinnedArrayElement(RequestBuffer, 0);
|
|
||||||
}
|
// HttpReceiveHttpRequest expects the request pointer to be 8-byte-aligned or it fails. On ARM
|
||||||
return RequestBlob;
|
// 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)
|
internal void Reset(ulong requestId, uint size)
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ namespace Microsoft.Net.Http.Server
|
||||||
_httpVersion = new Version(major, minor);
|
_httpVersion = new Version(major, minor);
|
||||||
}
|
}
|
||||||
|
|
||||||
_httpMethod = UnsafeNclNativeMethods.HttpApi.GetVerb(RequestBuffer, OriginalBlobAddress);
|
_httpMethod = UnsafeNclNativeMethods.HttpApi.GetVerb(RequestBuffer, BufferAlignment, OriginalBlobAddress);
|
||||||
_headers = new HeaderCollection(new RequestHeaders(_nativeRequestContext));
|
_headers = new HeaderCollection(new RequestHeaders(_nativeRequestContext));
|
||||||
|
|
||||||
var requestV2 = (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_V2*)memoryBlob.RequestBlob;
|
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
|
internal IntPtr OriginalBlobAddress
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -329,7 +338,7 @@ namespace Microsoft.Net.Http.Server
|
||||||
{
|
{
|
||||||
if (_remoteEndPoint == null)
|
if (_remoteEndPoint == null)
|
||||||
{
|
{
|
||||||
_remoteEndPoint = UnsafeNclNativeMethods.HttpApi.GetRemoteEndPoint(RequestBuffer, OriginalBlobAddress);
|
_remoteEndPoint = UnsafeNclNativeMethods.HttpApi.GetRemoteEndPoint(RequestBuffer, BufferAlignment, OriginalBlobAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _remoteEndPoint;
|
return _remoteEndPoint;
|
||||||
|
|
@ -342,7 +351,7 @@ namespace Microsoft.Net.Http.Server
|
||||||
{
|
{
|
||||||
if (_localEndPoint == null)
|
if (_localEndPoint == null)
|
||||||
{
|
{
|
||||||
_localEndPoint = UnsafeNclNativeMethods.HttpApi.GetLocalEndPoint(RequestBuffer, OriginalBlobAddress);
|
_localEndPoint = UnsafeNclNativeMethods.HttpApi.GetLocalEndPoint(RequestBuffer, BufferAlignment, OriginalBlobAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _localEndPoint;
|
return _localEndPoint;
|
||||||
|
|
@ -406,7 +415,7 @@ namespace Microsoft.Net.Http.Server
|
||||||
|
|
||||||
internal UnsafeNclNativeMethods.HttpApi.HTTP_VERB GetKnownMethod()
|
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.
|
// 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)
|
private string GetKnownHeader(HttpSysRequestHeader header)
|
||||||
{
|
{
|
||||||
return UnsafeNclNativeMethods.HttpApi.GetKnownHeader(_requestMemoryBlob.RequestBuffer,
|
return UnsafeNclNativeMethods.HttpApi.GetKnownHeader(_requestMemoryBlob.RequestBuffer,
|
||||||
_requestMemoryBlob.OriginalBlobAddress, (int)header);
|
_requestMemoryBlob.BufferAlignment, _requestMemoryBlob.OriginalBlobAddress, (int)header);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetUnknownHeaders(IDictionary<string, StringValues> extra)
|
private void GetUnknownHeaders(IDictionary<string, StringValues> extra)
|
||||||
{
|
{
|
||||||
UnsafeNclNativeMethods.HttpApi.GetUnknownHeaders(extra, _requestMemoryBlob.RequestBuffer,
|
UnsafeNclNativeMethods.HttpApi.GetUnknownHeaders(extra, _requestMemoryBlob.RequestBuffer,
|
||||||
_requestMemoryBlob.OriginalBlobAddress);
|
_requestMemoryBlob.BufferAlignment, _requestMemoryBlob.OriginalBlobAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IDictionary<string, StringValues>.Add(string key, StringValues value)
|
void IDictionary<string, StringValues>.Add(string key, StringValues value)
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,9 @@ namespace Microsoft.Net.Http.Server
|
||||||
|
|
||||||
if (_dataChunkIndex != -1)
|
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)
|
if (_dataChunkIndex == -1 && dataRead < size)
|
||||||
|
|
@ -223,7 +225,9 @@ namespace Microsoft.Net.Http.Server
|
||||||
uint dataRead = 0;
|
uint dataRead = 0;
|
||||||
if (_dataChunkIndex != -1)
|
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)
|
if (_dataChunkIndex != -1 && dataRead == size)
|
||||||
{
|
{
|
||||||
asyncResult = new RequestStreamAsyncResult(this, state, callback, buffer, offset, 0);
|
asyncResult = new RequestStreamAsyncResult(this, state, callback, buffer, offset, 0);
|
||||||
|
|
@ -339,7 +343,8 @@ namespace Microsoft.Net.Http.Server
|
||||||
uint dataRead = 0;
|
uint dataRead = 0;
|
||||||
if (_dataChunkIndex != -1)
|
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)
|
if (_dataChunkIndex != -1 && dataRead == size)
|
||||||
{
|
{
|
||||||
UpdateAfterRead(UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS, dataRead);
|
UpdateAfterRead(UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS, dataRead);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue