private void SendError(ulong requestId, HttpStatusCode httpStatusCode, ArrayList challenges)
{
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"RequestId: {requestId}");
Interop.HttpApi.HTTP_RESPONSE httpResponse = new Interop.HttpApi.HTTP_RESPONSE();
httpResponse.Version = new Interop.HttpApi.HTTP_VERSION();
httpResponse.Version.MajorVersion = (ushort)1;
httpResponse.Version.MinorVersion = (ushort)1;
httpResponse.StatusCode = (ushort)httpStatusCode;
string statusDescription = HttpStatusDescription.Get(httpStatusCode);
uint DataWritten = 0;
uint statusCode;
byte[] byteReason = Encoding.Default.GetBytes(statusDescription);
fixed (byte* pReason = byteReason)
{
httpResponse.pReason = (sbyte*)pReason;
httpResponse.ReasonLength = (ushort)byteReason.Length;
byte[] byteContentLength = Encoding.Default.GetBytes("0");
fixed (byte* pContentLength = byteContentLength)
{
(&httpResponse.Headers.KnownHeaders)[(int)HttpResponseHeader.ContentLength].pRawValue = (sbyte*)pContentLength;
(&httpResponse.Headers.KnownHeaders)[(int)HttpResponseHeader.ContentLength].RawValueLength = (ushort)byteContentLength.Length;
httpResponse.Headers.UnknownHeaderCount = checked((ushort)(challenges == null ? 0 : challenges.Count));
GCHandle[] challengeHandles = null;
Interop.HttpApi.HTTP_UNKNOWN_HEADER[] headersArray = null;
GCHandle headersArrayHandle = new GCHandle();
GCHandle wwwAuthenticateHandle = new GCHandle();
if (httpResponse.Headers.UnknownHeaderCount > 0)
{
challengeHandles = new GCHandle[httpResponse.Headers.UnknownHeaderCount];
headersArray = new Interop.HttpApi.HTTP_UNKNOWN_HEADER[httpResponse.Headers.UnknownHeaderCount];
}
try
{
if (httpResponse.Headers.UnknownHeaderCount > 0)
{
headersArrayHandle = GCHandle.Alloc(headersArray, GCHandleType.Pinned);
httpResponse.Headers.pUnknownHeaders = (Interop.HttpApi.HTTP_UNKNOWN_HEADER*)Marshal.UnsafeAddrOfPinnedArrayElement(headersArray, 0);
wwwAuthenticateHandle = GCHandle.Alloc(s_WwwAuthenticateBytes, GCHandleType.Pinned);
sbyte* wwwAuthenticate = (sbyte*)Marshal.UnsafeAddrOfPinnedArrayElement(s_WwwAuthenticateBytes, 0);
for (int i = 0; i < challengeHandles.Length; i++)
{
byte[] byteChallenge = Encoding.Default.GetBytes((string)challenges[i]);
challengeHandles[i] = GCHandle.Alloc(byteChallenge, GCHandleType.Pinned);
headersArray[i].pName = wwwAuthenticate;
headersArray[i].NameLength = (ushort)s_WwwAuthenticateBytes.Length;
headersArray[i].pRawValue = (sbyte*)Marshal.UnsafeAddrOfPinnedArrayElement(byteChallenge, 0);
headersArray[i].RawValueLength = checked((ushort)byteChallenge.Length);
}
}
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendHtthttpResponse");
statusCode =
Interop.HttpApi.HttpSendHttpResponse(
_requestQueueHandle,
requestId,
0,
&httpResponse,
null,
&DataWritten,
SafeLocalAllocHandle.Zero,
0,
null,
null);
}
finally
{
if (headersArrayHandle.IsAllocated)
{
headersArrayHandle.Free();
}
if (wwwAuthenticateHandle.IsAllocated)
{
wwwAuthenticateHandle.Free();
}
if (challengeHandles != null)
{
for (int i = 0; i < challengeHandles.Length; i++)
{
if (challengeHandles[i].IsAllocated)
{
challengeHandles[i].Free();
}
}
}
}
}
}
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendHttpResponse returned:" + statusCode);
if (statusCode != Interop.HttpApi.ERROR_SUCCESS)
{
// if we fail to send a 401 something's seriously wrong, abort the request
if (NetEventSource.IsEnabled) NetEventSource.Info(this, "SendUnauthorized returned:" + statusCode);
HttpListenerContext.CancelRequest(_requestQueueHandle, requestId);
}
}