private static void OnRequestError(WinHttpRequestState state, Interop.WinHttp.WINHTTP_ASYNC_RESULT asyncResult)
{
WinHttpTraceHelper.TraceAsyncError("OnRequestError", asyncResult);
Debug.Assert(state != null, "OnRequestError: state is null");
Exception innerException = WinHttpException.CreateExceptionUsingError((int)asyncResult.dwError);
switch ((uint)asyncResult.dwResult.ToInt32())
{
case Interop.WinHttp.API_SEND_REQUEST:
state.LifecycleAwaitable.SetException(innerException);
break;
case Interop.WinHttp.API_RECEIVE_RESPONSE:
if (asyncResult.dwError == Interop.WinHttp.ERROR_WINHTTP_RESEND_REQUEST)
{
state.RetryRequest = true;
state.LifecycleAwaitable.SetResult(0);
}
else if (asyncResult.dwError == Interop.WinHttp.ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED)
{
// WinHttp will automatically drop any client SSL certificates that we
// have pre-set into the request handle including the NULL certificate
// (which means we have no certs to send). For security reasons, we don't
// allow the certificate to be re-applied. But we need to tell WinHttp
// explicitly that we don't have any certificate to send.
Debug.Assert(state.RequestHandle != null, "OnRequestError: state.RequestHandle is null");
WinHttpHandler.SetNoClientCertificate(state.RequestHandle);
state.RetryRequest = true;
state.LifecycleAwaitable.SetResult(0);
}
else if (asyncResult.dwError == Interop.WinHttp.ERROR_WINHTTP_OPERATION_CANCELLED)
{
state.LifecycleAwaitable.SetCanceled(state.CancellationToken);
}
else
{
state.LifecycleAwaitable.SetException(innerException);
}
break;
case Interop.WinHttp.API_QUERY_DATA_AVAILABLE:
if (asyncResult.dwError == Interop.WinHttp.ERROR_WINHTTP_OPERATION_CANCELLED)
{
// TODO: Issue #2165. We need to pass in the cancellation token from the
// user's ReadAsync() call into the TrySetCanceled().
Debug.WriteLine("RequestCallback: QUERY_DATA_AVAILABLE - ERROR_WINHTTP_OPERATION_CANCELLED");
state.LifecycleAwaitable.SetCanceled();
}
else
{
state.LifecycleAwaitable.SetException(
new IOException(SR.net_http_io_read, innerException));
}
break;
case Interop.WinHttp.API_READ_DATA:
if (asyncResult.dwError == Interop.WinHttp.ERROR_WINHTTP_OPERATION_CANCELLED)
{
// TODO: Issue #2165. We need to pass in the cancellation token from the
// user's ReadAsync() call into the TrySetCanceled().
Debug.WriteLine("RequestCallback: API_READ_DATA - ERROR_WINHTTP_OPERATION_CANCELLED");
state.LifecycleAwaitable.SetCanceled();
}
else
{
state.LifecycleAwaitable.SetException(new IOException(SR.net_http_io_read, innerException));
}
break;
case Interop.WinHttp.API_WRITE_DATA:
if (asyncResult.dwError == Interop.WinHttp.ERROR_WINHTTP_OPERATION_CANCELLED)
{
// TODO: Issue #2165. We need to pass in the cancellation token from the
// user's WriteAsync() call into the TrySetCanceled().
Debug.WriteLine("RequestCallback: API_WRITE_DATA - ERROR_WINHTTP_OPERATION_CANCELLED");
state.TcsInternalWriteDataToRequestStream.TrySetCanceled();
}
else
{
state.TcsInternalWriteDataToRequestStream.TrySetException(
new IOException(SR.net_http_io_write, innerException));
}
break;
default:
Debug.Fail(
"OnRequestError: Result (" + asyncResult.dwResult + ") is not expected.",
"Error code: " + asyncResult.dwError + " (" + innerException.Message + ")");
break;
}
}
}