private static void IOCompleted(ListenerAsyncResult asyncResult, uint errorCode, uint numBytes)
{
object result = null;
try
{
if (NetEventSource.IsEnabled)
{
NetEventSource.Info(null, $"errorCode:[{errorCode}] numBytes:[{numBytes}]");
}
if (errorCode != Interop.HttpApi.ERROR_SUCCESS &&
errorCode != Interop.HttpApi.ERROR_MORE_DATA)
{
asyncResult.ErrorCode = (int)errorCode;
result = new HttpListenerException((int)errorCode);
}
else
{
HttpListener httpWebListener = asyncResult.AsyncObject as HttpListener;
if (errorCode == Interop.HttpApi.ERROR_SUCCESS)
{
// at this point we have received an unmanaged HTTP_REQUEST and memoryBlob
// points to it we need to hook up our authentication handling code here.
bool stoleBlob = false;
try
{
if (httpWebListener.ValidateRequest(asyncResult._requestContext))
{
result = httpWebListener.HandleAuthentication(asyncResult._requestContext, out stoleBlob);
}
}
finally
{
if (stoleBlob)
{
// The request has been handed to the user, which means this code can't reuse the blob. Reset it here.
asyncResult._requestContext = result == null ? new AsyncRequestContext(httpWebListener.RequestQueueBoundHandle, asyncResult) : null;
}
else
{
asyncResult._requestContext.Reset(httpWebListener.RequestQueueBoundHandle, 0, 0);
}
}
}
else
{
asyncResult._requestContext.Reset(httpWebListener.RequestQueueBoundHandle, asyncResult._requestContext.RequestBlob->RequestId, numBytes);
}
// We need to issue a new request, either because auth failed, or because our buffer was too small the first time.
if (result == null)
{
uint statusCode = asyncResult.QueueBeginGetContext();
if (statusCode != Interop.HttpApi.ERROR_SUCCESS &&
statusCode != Interop.HttpApi.ERROR_IO_PENDING)
{
// someother bad error, possible return values are:
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
result = new HttpListenerException((int)statusCode);
}
}
if (result == null)
{
return;
}
}
// complete the async IO and invoke the callback
if (NetEventSource.IsEnabled)
{
NetEventSource.Info(null, "Calling Complete()");
}
}
catch (Exception exception) when(!ExceptionCheck.IsFatal(exception))
{
if (NetEventSource.IsEnabled)
{
NetEventSource.Info(null, $"Caught exception: {exception}");
}
result = exception;
}
asyncResult.InvokeCallback(result);
}